clojurescript

2025-01-29T17:11:37.993239Z

(defn create-parquet []
  (go
    (let [{:keys [stream get-buffer]} (create-memory-stream)
          schema (parquet/ParquetSchema. (clj->js {
                                                   :name {:type "UTF8"}
                                                   :age  {:type "INT64"}
                                                   }))
          opts #js {}
          writer (
Is anyone able to offer any insight on why only the last log statement doesn't seem to execute? As soon as I wait for that .close, nothing else runs after it. This happens with .then too btw.

2025-01-30T08:27:33.735239Z

@caleb.macdonaldblack that worked just fine, much appreciated!

2025-01-30T08:28:05.569329Z

I ended up going with stream-buffers

2025-01-30T08:28:38.317629Z

@p-himik thanks for the js-await suggestion!

2025-01-30T08:29:08.667949Z

And many thanks to everyone else who chipped in

p-himik 2025-01-29T17:37:33.290019Z

Probably because the future returned by .close doesn't get resolved. As to "why" - no clue, that would be a question for the authors of the Parquet library.

p-himik 2025-01-29T17:38:45.353689Z

Have you tried removing the calls to log/spy? No clue how that would work, but maybe it holds some references inside writer that prevent it from being closed.

lilactown 2025-01-29T18:00:39.981579Z

could it be that .close is throwing?

2025-01-29T20:04:18.380169Z

@lilactown that does make the most sense to me, but I can't catch anything...

2025-01-29T20:04:42.472659Z

Consider the following:

(defn create-parquet []
  (let [{:keys [stream get-buffer]} (create-memory-stream)
        schema (parquet/ParquetSchema. (clj->js {
                                                 :name {:type "UTF8"}
                                                 :age  {:type "INT64"}
                                                 }))
        opts #js {}]
    (-> (prom/let [writer (parquet/ParquetWriter.openStream schema stream opts)
                   _ (.appendRow writer #js {:name "apples" :age 10})
                   _ (.close writer)
                   ]
          writer)
        (prom/handle (fn [result error]
                       (log/spy result)
                       (log/spy error))))))

2025-01-29T20:05:15.052269Z

This will print nothing at all

2025-01-29T20:06:05.852519Z

if I comment _ (.close writer) , that (spy result) will print the writer object...

2025-01-29T20:07:27.942109Z

So it does seem that .close is blowing up, but I should see something on the error arg of handle , right

2025-01-29T20:08:43.935389Z

I can't see anything that would eat up the error. JS is not my forte though...

p-himik 2025-01-29T20:36:27.870759Z

It accepts a callback. If you pass something, does it ever get called?

caleb.macdonaldblack 2025-01-29T23:20:38.756969Z

Some of the writers i tried don’t call the promise callback. this works though:

(defn create-parquet []
  (async/go
    (let [schema    (new (.-ParquetSchema parquetjs) (clj->js {:name {:type "UTF8"} :age {:type "INT64"}}))
          stream (new (.-PassThrough readable-stream))
          writer    (<p! (.openStream (.-ParquetWriter parquetjs) schema stream (clj->js {})))]
      (spy "A" writer)
      (<p! (.appendRow writer #js {:name "apples" :age 10}))
      (spy "B" writer)
      (<p! (.appendRow writer #js {:name "oranges" :age 11}))
      (spy "C" writer)
      (js/console.log writer)
      (<p! (doto (.close writer)
                 (js/console.log)))
      (spy "D" writer))))

p-himik 2025-01-29T23:22:47.348009Z

Stuff like (new (.-PassThrough readable-stream)) can be written as (readable-stream/PassThrough.) (assuming readable-stream is an alias coming from :require).

caleb.macdonaldblack 2025-01-29T23:23:26.753629Z

woah thanks!

caleb.macdonaldblack 2025-01-30T00:25:30.734989Z

This one repoduces the problem:

(defn create-parquet []
  (async/go
    (let [schema    (new (.-ParquetSchema parquetjs) (clj->js {:name {:type "UTF8"} :age {:type "INT64"}}))
          ;stream (new (.-PassThrough readable-stream))

          newHandle (<p! (js/window.showSaveFilePicker))
          stream    (<p! (.createWritable newHandle))

          writer    (<p! (.openStream (.-ParquetWriter parquetjs) schema stream (clj->js {})))]
      (spy "A" writer)
      (<p! (.appendRow writer #js {:name "apples" :age 10}))
      (spy "B" writer)
      (<p! (.appendRow writer #js {:name "oranges" :age 11}))
      (spy "C" writer)
      (js/console.log writer)
      (<p! (doto (.close writer)
                 (js/console.log)))
      (spy "D" writer))))

caleb.macdonaldblack 2025-01-30T00:25:46.017389Z

But I can’t see the source code because its internal to the browser

caleb.macdonaldblack 2025-01-30T00:27:23.560529Z

Specifically here

caleb.macdonaldblack 2025-01-30T00:27:59.370169Z

caleb.macdonaldblack 2025-01-30T00:28:09.696349Z

A.write

caleb.macdonaldblack 2025-01-30T00:30:11.302089Z

const oswrite = function (os, buf) {
    return new Promise((resolve, reject) => {
        os.write(buf, (err) => {
            if (err) {
                reject(err);
            }
            else {
                resolve(err);
            }
        });
    });
};

caleb.macdonaldblack 2025-01-30T00:30:43.950039Z

That code is fine. I think there is something wrong with the implementation of .write on some streams

p-himik 2025-01-30T00:32:30.468689Z

I'd try creating a minimal reproducible example in plain JS and posting it on their issue tracker since at this point it has nothing to do with CLJS at all.

caleb.macdonaldblack 2025-01-30T00:42:37.149299Z

agreed

caleb.macdonaldblack 2025-01-30T00:42:41.749909Z

the clojure here is fine

p-himik 2025-01-30T00:45:10.926959Z

Just in case you haven't seen me mentioning it times and times again on this server - I'd still ditch core.async here. :) The use case is trivial, plain promise interop or the js-await macro available in shadow-cljs (that you can just copy from there, it's small) would be perfectly fine, with zero overload and no potential debugging or externs inference issues.

caleb.macdonaldblack 2025-01-30T01:01:15.445939Z

yeah I’ve never use core.async outside of experimentation.

caleb.macdonaldblack 2025-01-30T01:01:25.799539Z

js/Promise & futures go pretty far

Drew Verlee 2025-01-29T21:30:48.605779Z

Is there a way to know at the cljs repl if a javascript objects member is going to get munged in advanced compilation so i can know if i need to use goog.object or if i can use the dot syntax?

p-himik 2025-01-29T21:33:08.211459Z

No. Use the dot syntax for all code, add ^js as necessary. Use goog.object for data. Or unchecked-get.

➕ 1
Drew Verlee 2025-01-29T21:42:17.767039Z

Can you elaborate on what you mean by code vs data here? By data do we mean something that can only be learned at runtime? As in, we fetch some json from over the wire.

p-himik 2025-01-29T21:52:30.364239Z

Can be a compile-time constant - #js {...}. Can be something coming from a JS library. Or from js-obj.

Drew Verlee 2025-01-29T21:53:48.718339Z

Your saying that "code" can be a compiled time constant, right?

p-himik 2025-01-29T22:04:49.084369Z

No, that data can be.

p-himik 2025-01-29T22:05:21.790839Z

Code is already most often a compiled-time thing. Very, very rarely does one have to create some actual code at run time.

👀 1