Comments (11)
An alternative implementation is to have some sort of post-ref transformation that's applied after keys have been referenced.
(defmethod ig/init-key ::service [_ _]
{:exec-service (create-exec-service) :datascript-conn (create-conn)})
(defmethod ig/deref-key ::service [_ {:keys [datascript-conn]}]
@datascript-conn)
(defmethod ig/halt-key! ::service [_ {:keys [exec-service]}]
(.stop exec-service))
Let me think about this.
from integrant.
I've added a resolve-key
method to Integrant that works in the same way as deref-key
in my previous command. It's currently released as 0.8.0-alpha1.
As an alpha release, this functionality may change if I discover there's a problem with it, but if you want to try it out, please let me know how you get on with it.
from integrant.
Nice! I gave it a shot, and I found one bug so far:
It works when initially loading state, but after calling (reset)
, the private state is passed to the consumer components, instead of the thing returned from resolve-key
.
One other thing is that with the current approach, it isn't possible to update the object client components see without restarting the system. So the current approach would work if one for example returned an object that dereferences private state, e.g.,:
(reify SomeImmutableProtocol
(nth [_ n] (aget (:my-array private-state) n)
(count [_] (alength (:my-array private-state)))
But if you wanted to return a snapshot (i.e., something that cannot change, like how the above object could return different lengths at different points in time) instead, you wouldn't be able to (*). (An example would be returning @my-datascript-conn
.)
Technically it is not true that you wouldn't be able to pass different objects at different points in time to client components, because you could just return (reify IDeref [_] ...
) from resolve-key, though here it seems like you are encouraging approach 1 over approach 2, though I think approach 2 is the more robust and idiomatic in Clojure.
What do you think about requiring a deref (or 0 arity function invocation) on the value returned from resolve-key
in client components before use?
from integrant.
It works when initially loading state, but after calling
(reset)
, the private state is passed to the consumer components, instead of the thing returned fromresolve-key
.
Ah, right. The resume
function is missing the extra resolve argument. That should be an easy fix.
One other thing is that with the current approach, it isn't possible to update the object client components see without restarting the system.
Sorry, I don't understand what you mean by this. Could you explain your use-case?
from integrant.
My use case is to load a ton of data into an in-memory db, and then periodically update it incrementally from a standard relational database. I then want to expose a read-only view of the current value of this in-memory db to other components.
With the current approach, I can only do one of these things:
- Expose a read-only view of the initial value.
- Return an object that proxies read-type calls to an object that may change from under me. (Not idiomatic, hard to reason about)
- Return something like
(reify IDeref (deref [_] (get-snapshot private-state))
fromresolve-key
, then deref the input to client components from this component before use
I think 3 is probably about as good as it gets from the client component point of view, though it could be made better from the source component point of view.
So far you've solved the private-state vs public state problem, though not the snapshot-can-change-over-time problem. Not sure if you agree with me that the latter is an important use case.
from integrant.
Thanks for explaining. I don't think this is a use-case that's tied to Integrant in particular. Integrant handles initiating a dependency graph of components, but once the system is started it has little to no involvement. Even halting is something of a concession to REPL-based development, since in production you can't guarantee halt!
will ever be called on the system.
If you want something that looks like state, either wrap it in a IDeref
, as you pointed out, or supply an atom that's updated with a new database snapshot whenever the data is refreshed.
from integrant.
Ok, I understand. Sounds good.
from integrant.
The resume
issue should be fixed in 0.8.0-alpha2.
from integrant.
Great, works now 👍 .
I see that if I fetch an item from the system manually when playing at the REPL, I get the private state instead of the resolved value. Is there a way to get the resolved value when working at the REPL (without creating a new component)?
from integrant.
No, and I think the system should contain the "private" state. I think it's one thing to change what is passed via a reference, but quite another to hide the state entirely.
If you want to make it clear, you could put all the public state under a :public
key, and all the private state under :private
, then you could write (-> system :foo :public)
to get the public reference.
from integrant.
@weavejester - Ok, thanks.
from integrant.
Related Issues (20)
- Uninitialized/literal configs HOT 1
- Tests don't run with 1.11 due to clojure.test/run-test already being defined HOT 1
- Feature proposal: expand-key HOT 2
- Any way to add constant key in `edn`? HOT 2
- Unable to access Presentations(Enter Integrant) HOT 3
- Perhaps use metadata as an alternative to resolve-key? HOT 2
- Refs/Refsets not preserved after expansion HOT 1
- Convenience tag to add methods for static keys HOT 1
- Is there a way to analyze components at the repl with their config resolved ? HOT 1
- Would you consider an integrant2 to support extensible build steps? HOT 10
- Why does resume halt unspecified system keys? HOT 4
- Support usage in Babashka environments HOT 20
- #{:idea} Pass the spec validations step on all defined states before calling init-key. HOT 1
- is it possible to access a component after it's init-key, but before it gets passed to the next key that depends on it? HOT 2
- Enter Integrant Video
- Add support for custom assertf definitions HOT 2
- Question: Extract "validation keys" logic from core/build implementation HOT 4
- Feature request: pre-init hook
- No method in multimethod 'init-key' for dispatch value HOT 2
- #ig/ref should allow for deep references HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from integrant.