Giter Club home page Giter Club logo

Comments (11)

weavejester avatar weavejester commented on May 19, 2024 1

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.

weavejester avatar weavejester commented on May 19, 2024

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.

isaksky avatar isaksky commented on May 19, 2024

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.

weavejester avatar weavejester commented on May 19, 2024

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.

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.

isaksky avatar isaksky commented on May 19, 2024

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:

  1. Expose a read-only view of the initial value.
  2. Return an object that proxies read-type calls to an object that may change from under me. (Not idiomatic, hard to reason about)
  3. Return something like (reify IDeref (deref [_] (get-snapshot private-state)) from resolve-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.

weavejester avatar weavejester commented on May 19, 2024

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.

isaksky avatar isaksky commented on May 19, 2024

Ok, I understand. Sounds good.

from integrant.

weavejester avatar weavejester commented on May 19, 2024

The resume issue should be fixed in 0.8.0-alpha2.

from integrant.

isaksky avatar isaksky commented on May 19, 2024

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.

weavejester avatar weavejester commented on May 19, 2024

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.

isaksky avatar isaksky commented on May 19, 2024

@weavejester - Ok, thanks.

from integrant.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.