This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
Has anyone played around with http://temporal.io and Clojure and refactored existing code as workflows and activities? (If yes, how was your experience?)
I have! It was not bad at all! Took little time refactoring the code. The hardest part was utilizing the Temporal model and optimizing our configuration to get the most out of the Temporal runtime. Temporal runs stuff pretty easily The ‘temporal-clojure-sdk’ was a big help as well!
@U05NZDGDYG3 Did you get this feeling while doing so, that a regular codebase that doesn't use temporal can also benefit from having different naming convention for what's a workflow, side effect and what's an activity. And you could potentially roll out your own retry mechanism if you can distinguish between these?
I think if you are using Clojure these things just tend to happen naturally because we already have naming conventions for functions with side effects vs pure functions. That is why I think Clojure lends itself to just being easy to migrate to Temporal since everything is already organized as a "function"
Anyone has hacked Component such that each component receives other components (i.e. its dependencies), already started? It's a pattern that I got used to from Integrant usage
e.g. given Component Foo
that depends on Bar
, I want that after Foo
is started, it gets the started instance of Bar
assoced into it
All automated and following the system's dependency order
Stupid question - why? It's sort of what happens on components' start, where every dependency is updated with start
before the parent
Following my previous example, if an instance of Foo
can access the instance of Bar
by just accessing (:bar this)
- it's simply more ergonomic to use throughout the app, I believe
i.e. in the codebase, functions always depend on exactly one component which seems better than:
• N positional arguments (one per component)
• the whole system
• an ad-hoc subsystem (slice of the system) without a formal definition
In component, when a specific component starts, all its dependencies are already started and assoc
ed into it
Even pulled this pattern out to a little helper lib https://github.com/bsless/companion
Nice, I fully agree on your project's problem statement (which is a more proper answer to @U9MKYDN4Q's question) > In component, when a specific component starts, all its dependencies are already started and assoced into it I probably just forgot about this, long time no Component ...I'm in the middle of a big project cleanup, so a dozen things were broken, so at times it's hard to distinguish "truly broken" from "faulty refactor" 😇
btw whenever I can use Component, I use metadata-based protocol extension, which is fun enough, among other advantages. Probably if it was there 10 years ago we wouldn't have had the same explosion of alternatives
Another thing I adopted using component is making a component for everything that can be an argument
See https://github.com/bsless/companion/blob/master/examples/reitit/ring/server.clj#L222 for example
That's nice 👍 Although I used that fine-grainedness earlier this year with Integrant earlier this year and it made me nervous tbh. I like understanding a System as a moderate number of modules with clear responsibities. Anything smaller than that might as well be considered config? With aero or whatnot
and having the same "shape" for your system and config allows you to (merge-with merge config system)
just like that
A couple of things I dislike is any digging into config at runtime or a component digging into its children
> and having the same "shape" for your system and config allows you to (merge-with merge config system)
just like that
Yeah personally I disagree with that goal, I tend to like code and data separated (System = code, config = data)
I'm playing around with the idea of moving as much of the system's configuration to data
But code is dataYeah, there's always that objection, but even in Clojure itself there are quite a few exceptions - it has misc affordances which make it not map 1:1 to an AST? Or in any case code-as-data tends to be unsafe and complected. Of course there's a path to convert one to another, but they (IMO) should remain sharply distinct.
...back to my OP, I had this bug:
- component/start
+ component/start-system
which is why I was seeing an incomplete system, I believe.(defrecord SystemMap []
Lifecycle
(start [system]
(start-system system))
(stop [system]
(stop-system system)))
Probably I was using system-map with some modifications on top Anyway, I got past these issues and am closer to enjoying Component again :)
> if an instance of Foo
can access the instance of Bar
by just accessing (:bar this)
- it's simply more ergonomic to use throughout the app, I believe
I believe this is a wrong approach which will let you down. If component C needs A and B, and B depends on A, it's wrong to fetch B from A. Just add B and A as dependencies to C. Also, a component might act as a function if you implement IFf interface, namely:
(defrecord Myhandler [A B]
clojure.lang.IFn
(invoke [this request]
(do-something-with A)
(do-something-with B)
{:status 200 :body "OK"}))
Then you add an instance of Myhandler to the system, and when started, it gets populates with started A and B
@UK0810AQ2 companion
looks nice -- no releases to Clojars, so it's git-dep only? We often implement IFn
in our components but mostly so that (my-component)
=> state
-- implementing a "sensible" function of state, such execute!
or execute-one!
on a datasource
, is smart. We have a configuration component that implements 1- an 2-arity IFn
so (cfg :k)
and (cfg :k default)
work as keyed fetches from the state (the config map).
There are a couple of things I need to wrap up in companion before cutting a release and other things had higher priorities, so it kept getting pushed back. It does what I need it to, but without fleshing it out and a decent guide with examples I wouldn't recommend using it yet
Protocols question: if I am using a library that relies on protocols, can I add a new method to already-defined protocols? Or do I need to define a new protocol and "inherit" from the protocol I am trying to extend by repeating the implementations? Edit: here's a simplified example of how I'm thinking about it:
(defprotocol MyProto
(foo [arg] ...)
(bar [arg] ...))
(add-method MyProto
(baz [arg] ...))
am I thinking about protocols incorrectly here?You can just implement the existing protocol and a new protocol, you don’t need inheritance
To expand on that, if you need to implement a new protocol on anything that implements an existing protocol you can do a little hackery like so
(defprotocol MyProtoA
(foo [arg] ...)
(bar [arg] ...))
(defprotocol MyProtoB
(baz* [arg] ...))
(defn baz
[o]
(if (satisfies? MyProtoB o)
(baz* o)
(... (foo o) ... (bar o) ...)))
though obviously that is very context dependent and you probably don't want or need that
there are other ways even to get that effect, but you don't even need that - if you're making new stuff, make a new protocol
TCP TLS question: I fiddled a bit around today with TCP sockets in Aleph, and I want to test data streams between multiple different computers, just because fun. The thinking is that Aleph deals with the streams and TCP is natural for custom arbitrary data IO. But I've spent way too much time trying to get TLS up and running. Best examples I found was in https://github.com/clj-commons/aleph/blob/master/test/aleph/tcp_ssl_test.clj, but its not 'real' certificates, as in certificates generated by openssl and signed by your CA, the demo is using some other format. I just want to use some self-signed certs to see how the prod version would be. Part of my time was spent reading up on openssl and generating the certs. 15 years of changing guides, so a bit of pain there. Has anybody seen a good guide for TCP + TLS + Aleph ?
Have you seen https://github.com/aphyr/less-awful-ssl/ ? It's a bit dated, but hey... that library gives you an JDK SSLContext, which you can pass to netty (JdkSslContext last time I checked). I wrote a tiny lib for generating keys: https://github.com/ivarref/locksmith for using with nREPL TLS support. Some info on the nREPL TLS page: https://nrepl.org/nrepl/1.1/usage/tls.html Not sure how much that helps, but who knows? 🙃 The basic functionality of less-awful-ssl is replicated in nREPL TLS, but updated to use only TLS v1.3
Thanks! Tried for a couple of evenings, but too damn fiddly. I'll keep an eye out for anybody doing it in the future. I'm left more confused than anything 🤷
there is also https://github.com/FiloSottile/mkcert for making self signed certs and trusting them for local development
step-cli also makes it much easier to generate your own certificate structure, an example: https://github.com/claj/reproduce-pedestal-issue-38/blob/master/generate-pki.sh