Fork me on GitHub
#clojure
<
2019-11-14
>
phillippe00:11:58

i'm running into a weird issue where the google-cloud-pubsub library works in a standalone application, but when i include the same code in my luminus web application, the program hangs on waiting for the publish request to happen

phillippe00:11:17

here's the relevant code (which works fine on its own):

phillippe00:11:20

(ns pubsub-test.core
  (:require [clojure.tools.logging :as log]
            [mount.core :refer [defstate] :as mount])
  (:import (com.google.cloud ServiceOptions)
           (com.google.pubsub.v1 ProjectTopicName PubsubMessage)
           (com.google.cloud.pubsub.v1 Publisher)
           (com.google.protobuf ByteString))
  (:gen-class))

(defn- connect! [{:keys [topic-id]}]
  (-> (ServiceOptions/getDefaultProjectId)
      (ProjectTopicName/of topic-id)
      (Publisher/newBuilder)
      (.build)))

(defstate publisher
  :start (connect! {:topic-id "my-topic"})
  :stop (.shutdown publisher))

(defn publish! [message]
  (let [data (ByteString/copyFromUtf8 message)
        pubsubMessage (-> (PubsubMessage/newBuilder)
                          (.setData data)
                          (.build))]
    (.publish publisher pubsubMessage)))

(defn -main [& _args]
  (do
    (mount/start)
    (let [message-id (-> (publish! "Hello, World!")
                         (.get))]
      (log/info "Message ID: " message-id))))

phillippe00:11:10

at this point i'm guessing that some executor is failing to run the publish request, but i don't have any hypotheses as to why this would only be an issue in the luminus application

phillippe05:11:05

in case anyone is interested i figured out the issue. luminus includes google closure to support clojurescript. both com.google.javascript/closure-compiler-unshaded and com.google.cloud/google-cloud-pubsub depend on protobuf-java. unfortunately, they depend on different, incompatible versions

👍 4
henrik07:11:51

You could try overriding the Luminus one.

👍 4
Setzer2210:11:09

Hi! is there an alternative to core.match that I can use to store patterns to be matched as data and not have to rely on the match macro? To clarify, what I'd like is to have something like this:

(def patterns
  '[[_ 1 2]
    [a b c]
    [a b]
    [_ & tail]])

(let [my-data [0 1 2]]
  (doseq [pattern patterns]
    (println (matches? pattern))))

;; => {:match true :bindings {}}
;; => {:match true :bindings {:a 0 :b 1 :c 2}}
;; => {:match false}
;; => {:match true :bindings {:tail [1 2]}}

vlaaad10:11:10

store it as code and eval?

mpenet13:11:59

you could do it with clojure.spec conform

mpenet13:11:48

but difficult to say if it's a good idea or not with the info you give

plexus14:11:36

I have a namespace with a :gen-class (I need to subclass and to be accessible from Java): https://gist.github.com/1bf76fb6eb8f5217062db5b0f15e1167 When I compile this I get 60 .class files, i.e. the gen-class class, a dozen classes corresponding to vars in that namespace, and the rest from clojure.specs.alpha (see gist) what's the right way to distribute this? The generated class relies on some of those vars. can I just distribute the single class file + the clj file?

Alex Miller (Clojure team)14:11:48

no, you need all of those classes

Alex Miller (Clojure team)14:11:16

the ones from that namespace that is

Alex Miller (Clojure team)14:11:56

you don't need the core.specs.alpha ones (those were transitively compiled)

plexus14:11:15

thanks, I'll try that

Alex Miller (Clojure team)14:11:16

the clj file won't be used

plexus14:11:40

I'm getting a bit of a puzzling error. I'm referencing this in logback.xml, and when the process boots I get this

2019-11-14 15:35:08.689 INFO  org.eclipse.jetty.util.log - Logging initialized @62847ms to org.eclipse.jetty.util.log.Slf4jLog
Syntax error (ClassNotFoundException) compiling new at (ring/adapter/jetty.clj:31:3).
lambdaisland.logback.clojure_filter.proxy$org.eclipse.jetty.server.handler.AbstractHandler$ff19274a
When I take it out of logback.xml, start the process, then put it back in and wait for logback to rescan its config, then it works

vlaaad14:11:24

Compiling namespace with -Dclojure.spec.skip-macros=true does not produce spec classes

Eric Ihli16:11:30

I notice what seems to me to be a disproportionate number of UK/EU to US jobs being posted in #remote-jobs. Anyone have an idea about the reason for that? Does Clojure have a bigger market share, compared to other languages, outside of the U.S.?

Alex Miller (Clojure team)16:11:44

I don't think that's either true or that you can draw that conclusion from posting occurrence

borkdude16:11:10

I'm getting back a method for this:

(.getMethod String "contains" (into-array [CharSequence]))
I want to write my own method invocator that looks like:
(defn invokeMethod [^Object obj method args]
  (let [class (.getClass obj)
        method (.getMethod class method (into-array (map #(.getClass ^Object %) args)))]
    (.invoke method obj (into-array args))))
so it just gets all the classes from the args and then tries to find the matching method and invokes it. This doesn't go well with for example: (invokeMethod "foo" "contains" ["o"]) because then it tries to:
(.getMethod String "contains" (into-array [String]))
which doesn't return a method... How to solve this?

ghadi16:11:21

(.getClass %) on an argument may return a concrete class more specific than in the signature of the target method

ghadi16:11:17

tldr: you can't guess the right method to call in one shot if all you have is arguments

ghadi16:11:38

need to enumerate and filter

borkdude16:11:49

ok, that's useful information, thanks

Alex Miller (Clojure team)17:11:36

feel free to use the public Reflector methods if you're doing stuff like this

Alex Miller (Clojure team)17:11:25

because calls to that class get embedded in compiled reflective Clojure code, we generally try hard to only grow not break that class so it should be pretty stable

Alex Miller (Clojure team)17:11:45

but I would not consider it "official" public API

borkdude17:11:05

nice, that saves me a lot of work 🙂

rickmoynihan17:11:12

Does anyone know of any clojure libraries that wrap the java.nio.file.FileSystem stuff? Datoteka claims to have a file storage abstraction; but AFAICT it’s not the java one and doesn’t seem anywhere near as useful or complete.

borkdude22:11:10

I'm getting a reflection warning for this:

(defn invoke-static-method #?(:clj [_ctx [[^Class class method-name] & args]]
                              :cljs [_ctx & _args])
  #?(:clj
     (Reflector/invokeStaticMethod class (str method-name) (into-array args))
     :cljs (throw (js/Error. "Not imlemented yet."))))
Reflection warning, sci/impl/interop.cljc:20:6 - call to static method invokeStaticMethod on clojure.lang.Reflector can't be resolved (argument types: java.lang.Class, java.lang.String, unknown).

bronsa10:11:08

^objects (into-array args)

borkdude22:11:52

what type hint should be added for the args?

Derek22:11:40

Just a guess: (object-array args)

borkdude22:11:20

probably a good guess

chrisn22:11:18

^"[Ljava.lang.Object;"

chrisn22:11:48

Interestingly enough that will work for any object array, so typehinting (into-array String ["1" "2"]) as an object array is legal.

noisesmith22:11:13

the magic of inheretance

emccue22:11:14

Has anyone tried using the alpha java fiber api with clojure?

emccue22:11:34

they have some methods on fibers that are overloaded to take either a callable or a runnable

emccue22:11:10

so it feels like it will be prudent for std. lib / core.async support

emccue22:11:22

just like with (thread ...)

noisesmith22:11:03

oh wow, they are doing continuations

hiredman22:11:08

it is exciting isn't it

noisesmith22:11:43

if what they make is meaningfully a continuation, yeah, that seems like a big deal

hiredman23:11:27

I think it is technically a delimited continuation, and I am not sure what the exposed api will be, but it sounds like blocking operations in fibers will transparently turn into a callback thing with the current continuation , which is neat

bronsa10:11:20

Ron said they'll likely not expose the continuation api at first, but will do in the following releases

bronsa10:11:53

it's a full fledged multi-prompt delimited continuation system

hiredman23:11:38

it'll be great if it doesn't take 10 years to land

4
noisesmith23:11:57

an overview I saw just now mentioned coroutines, which means you could potentially have a core.async rewrite using yield for channel writes and resume for channel reads maybe?

seancorfield23:11:22

I think I saw @ghadi Had posted a Gist with some Clojure code interacting with fibers?

hiredman23:11:36

the degree to which core.async would need a rewrite depends on how transparently they handle it, if the fiber support in the jvm automatically turns blocking things like taking locks in to callbacks with continuations, then core.async doesn't really need rewriting, just use the "blocking" api in fibers and it will come out right

noisesmith23:11:38

the benefit I imagined is being able to use yield / resume in place of a state machine rewrite while still getting the right semantics, but maybe that's far fetched

hiredman23:11:53

if the continuation usage in fibers is entirely transparent, you can get rid of the go macro all together, >!! will behave like >! in fibers and continue to behave as does now outside of fibers

noisesmith23:11:42

yeah, it would potentially allow eliminating a lot of complexity

seancorfield23:11:18

@emccue ☝️:skin-tone-2:

emccue23:11:14

Yeah see part of the issue is that type hint won't work

emccue23:11:23

In the preview image

emccue23:11:47

He marks it as ^Runnable, but their API will always use the Callable methods if they are available

emccue23:11:03

So it's a bit of a nightmare

emccue23:11:23

Dep. on your views of API design

hiredman23:11:31

that isn't correct

hiredman23:11:42

the real issue is you can't type hint fns like that

hiredman23:11:12

the executor api has the same thing happen

hiredman23:11:26

if you bind the fn to a name and type hint the name everything is fine