babashka

https://github.com/babashka/babashka. Also see #sci, #nbb and #babashka-circleci-builds .
bartuka 2020-10-14T00:14:14.393400Z

hello guys, I am trying to use the s3-pod inside a bb app.. but I am having trouble to figure out what is the expected format for my :Body object in a PutObject operation. I tried to pass the same format as the aws-api from cognitect expects and got this error.

29: (defn run [opts]
30:   (let [{:keys [filepath partner content dag-name]} opts]
31:     (s3/put-object {:Bucket "captalys-analytics"
        ^--- Cannot JSON encode object of class: class java.io.BufferedInputStream: java.io.BufferedInputStream@7fa4620f4f20
32:                     :Key "testando"
33:                     :Body (io/input-stream (io/file filepath))
34:                     :Tagging "dagName=OK"})))

bartuka 2020-10-14T00:15:46.394600Z

If I try to pass bytes (as is specified in the go sdk) I then ge tthe following error

29: (defn run [opts]
30:   (let [{:keys [filepath partner content dag-name]} opts]
31:     (s3/put-object {:Bucket "captalys-analytics"
        ^--- json: cannot unmarshal string into Go struct field PutObjectInput.Body of type io.ReadSeeker
32:                     :Key "testando"
33:                     :Body (.getBytes "okokk")
34:                     :Tagging "dagName=OK"})))
seems like the msg is converting my bytes to string and the go structure cannot parse it

jumar 2020-10-14T03:33:05.394900Z

Does this work in the standard REPL? If not you may want to ask in #aws

bartuka 2020-10-14T03:34:44.395100Z

when using the aws-api from cognitect it works without a problem. The issue is the interface between clj and golang sdk managed by https://github.com/tzzh/pod-tzzh-aws

borkdude 2020-10-14T07:12:27.395700Z

@thomas.ormezzano ^

borkdude 2020-10-14T07:40:10.397200Z

@iagwanderson Have you tried passing in a string? The arguments to a pod are serialized via EDN or JSON, so there should be special handling of bytes in a pod (e.g. serialize to base64 under the hood in bb and deserialize to bytes at the pod side). This can be implemented so the user doesn't even notice, but it does need attention. Maybe @thomas.ormezzano can think about this?

tzzh 2020-10-14T09:01:13.398500Z

ah yes good point I am afraid bytes arguments are not supported atm I need to look into this

tzzh 2020-10-14T09:13:16.400Z

also I noticed there are a bunch of helpers functions in the s3manager module that could be helpful for uploading/downloading https://docs.aws.amazon.com/sdk-for-go/api/service/s3/s3manager/ - I mostly use the s3 fns for listing/deleting files so I haven’t looked into this as much but going to have a look when I have a bit of time

borkdude 2020-10-14T09:22:44.400500Z

@thomas.ormezzano Should be doable I think using a client side wrapper which coerces the bytes into base64 (or something similar which can go through json)

👍 1
borkdude 2020-10-14T09:36:21.403500Z

@thomas.ormezzano Maybe pods should start supporting transit. If there's a transit library for Go which supports bytes, then we could just use that

borkdude 2020-10-14T09:38:27.404400Z

@thomas.ormezzano Alternatively you could invent your own representation of bytes, like: {"tzzh/bytes" "base64string"} so if you encounter an arg like that on the pod side, deal with it You could even choose to just use bencode as the byte representation, since bencode supports sending just bytes I think

borkdude 2020-10-14T09:40:35.405Z

This is what I do with database connection objects and terminal objects in pods too. Right now I'm working on a lantera pod: https://github.com/babashka/pod-babashka-lanterna

tzzh 2020-10-14T09:46:09.405900Z

ok thanks I will take a look and see what’s easier :thumbsup:

borkdude 2020-10-15T09:33:33.429300Z

@thomas.ormezzano I now added transit+json support to babashka.pods and pushed it to bb master. To use this format, specify "format" "transit+json" in the describe message.

borkdude 2020-10-15T09:33:58.429500Z

This will allow you to send bytes back and forth, hopefully. I don't know how well the russolsen/transit lib works.

tzzh 2020-10-15T09:44:14.429700Z

ok cool thanks I had actually started looking at doing using base64 encoding (and add some client side code to do the decoding transparently) so maybe I’ll finish that first and look at transit after, it’s a bit hard to tell if the lib is good but it’d be cool to try it out either way

borkdude 2020-10-15T09:47:26.429900Z

:thumbsup:

borkdude 2020-10-14T11:24:07.406100Z

Found a Go transit lib here: https://github.com/russolsen/transit If you can verify that it's possible to serialize bytes using this lib, I'm willing to add support for transit to babashka.pods

bartuka 2020-10-14T12:05:44.407Z

hello guys, thanks for the comments. I tried to pass a plan string but got the same error

29: (defn run [opts]
30:   (let [{:keys [filepath partner content dag-name]} opts]
31:     (s3/put-object {:Bucket "captalys-analytics"
        ^--- json: cannot unmarshal string into Go struct field PutObjectInput.Body of type io.ReadSeeker
32:                     :Key "testando"
33:                     :Body "new string!"
34:                     :Tagging "dagName=OK"})))

borkdude 2020-10-14T12:12:28.407400Z

ok, there's not much you can do then right now. see the above.

tzzh 2020-10-14T12:12:39.407500Z

yeah you won’t be able to get this to work at the moment as the underlying go type is

Body io.ReadSeeker `type:"blob"
` 😕

tzzh 2020-10-14T12:13:09.408Z

I’ll try to find have a look later today/this week if I have time

👍 1
borkdude 2020-10-14T12:13:49.408200Z

meanwhile I will see if I can support transit in pods. would be nice either way

bartuka 2020-10-14T12:17:11.408400Z

ok, got it!

Dig 2020-10-14T17:09:26.409600Z

How do I check if var is bound in bb?

Babashka v0.2.2 REPL.
Use :repl/quit or :repl/exit to quit the REPL.
Clojure rocks, Bash reaches.

user=> (def a "a")
#'user/a
user=> (bound? #'a)
java.lang.ClassCastException: sci.impl.vars.SciVar cannot be cast to clojure.lang.Var [at <repl>:2:1]

borkdude 2020-10-14T17:20:02.410100Z

@i.slack Ah, that needs fixing. For now you can maybe use:

user=> (find-var 'user/a)
#'user/a

borkdude 2020-10-14T17:20:19.410400Z

or resolve / ns-resolve

borkdude 2020-10-14T17:21:57.410700Z

made an issue here: https://github.com/borkdude/sci/issues/430

Dig 2020-10-14T17:23:23.412200Z

I was trying to see if *file* is bound to distinguish from clj run

Dig 2020-10-14T17:23:52.412700Z

is there a better way to know that it is running in bb?

borkdude 2020-10-14T17:24:09.413Z

you can check (System/getProperty "babashka.version")

Dig 2020-10-14T17:24:31.413400Z

ahh, thank you! that would be much cleaner.

isak 2020-10-14T18:59:38.414100Z

For authoring pods, and this example for error handling:

{"id" "1d17f8fe-4f70-48bf-b6a9-dc004e52d056"
 "ex-message" "Illegal input"
 "ex-data" "{\"input\": 10}
 "status" "[\"done\", \"error\"]"}
What is the "status"? Do we need it?

borkdude 2020-10-14T19:10:01.416400Z

yes, error signals whether we should raise an error and done signals that it's the last message for this id

isak 2020-10-14T19:10:23.416600Z

oh ok, cool

borkdude 2020-10-14T19:17:09.416900Z

Meanwhile: tetris works in pod-babashka-lanterna :)

😎 6
isak 2020-10-14T19:25:37.418500Z

For replies from the pod where the messages send a few messages for a request id without being done, how are the messages accumulated/handled on the pod client?

borkdude 2020-10-14T19:27:42.418900Z

@isak you can check the source: https://github.com/babashka/babashka.pods/blob/master/src/babashka/pods/impl.clj

borkdude 2020-10-14T19:31:26.419400Z

@isak the README is also helpful maybe: https://github.com/babashka/babashka.pods#introduction

borkdude 2020-10-14T19:31:42.419900Z

typically for async functions you have multiple messages coming in

isak 2020-10-14T20:40:15.420600Z

:thinking_face: I've been reading that document, but I couldn't see that it was specified.

isak 2020-10-14T20:41:34.421500Z

Looked at the source, but not obvious what will happen without knowing how the functions in that namespace will be called. I guess I'll just experiment, will be faster

isak 2020-10-14T20:46:28.423Z

Makes sense if only async calls are involved with the :success, :error and :done callbacks, just not as obvious for the normal calls

borkdude 2020-10-14T20:53:28.424400Z

@isak Note that normal functions can also send multiple "out" messages which will be sent to stdout. Also they can send the value and status in separate messages.

borkdude 2020-10-14T20:53:53.424800Z

This is more or less the same as with the nREPL protocol

isak 2020-10-14T20:55:45.426Z

Ok makes sense. But only 1 message can deliver the value when not calling the async way, correct? @borkdude

borkdude 2020-10-14T20:56:26.426200Z

Correct

isak 2020-10-14T20:57:20.426600Z

Ok, then I'm no longer confused, thanks

isak 2020-10-14T23:01:54.427500Z

In a C# pod I'm trying to make, I'm getting an error from babashka when sending this message from the pod:

async Task SendResult(string id, object result) {
    var resp = new BDictionary {
        ["id"] = new BString(id),
        ["value"] = new BString("[]"),
        ["status"] = new BString(JsonSerializer.Serialize(new string[] { "done"}))
    };
    await _writer.WriteAsync(resp.EncodeAsBytes());
}
Error:
#error {
 :cause "java.lang.Byte cannot be cast to byte[]"
 :via
 [{:type java.lang.ClassCastException
   :message "java.lang.Byte cannot be cast to byte[]"
   :at [babashka.pods.impl$bytes__GT_string invokeStatic "impl.clj" 22]}]
 :trace
 [[babashka.pods.impl$bytes__GT_string invokeStatic "impl.clj" 22]
  [babashka.pods.impl$bytes__GT_string invoke "impl.clj" 22]
  [clojure.core$comp$fn__5811 invoke "core.clj" 2571]
  [clojure.core$map$fn__5870 invoke "core.clj" 2757]
  [clojure.lang.LazySeq sval "LazySeq.java" 42]
  [clojure.lang.LazySeq seq "LazySeq.java" 51]
  [clojure.lang.RT seq "RT.java" 535]
  [clojure.core$seq__5405 invokeStatic "core.clj" 137]
  [clojure.core$reduce1 invokeStatic "core.clj" 930]
  [clojure.core$set invokeStatic "core.clj" 4115]
  [babashka.pods.impl$processor invokeStatic "impl.clj" 108]
  [babashka.pods.sci$fn__15492$fn__15525 invoke "sci.clj" 67]
  [sci.impl.vars$binding_conveyor_fn$fn__7722 invoke "vars.cljc" 144]
  [clojure.core$binding_conveyor_fn$fn__5758 invoke "core.clj" 2032]
  [clojure.lang.AFn call "AFn.java" 18]
  [java.util.concurrent.FutureTask run "FutureTask.java" 264]
  [java.util.concurrent.ThreadPoolExecutor runWorker "ThreadPoolExecutor.java" 1128]
  [java.util.concurrent.ThreadPoolExecutor$Worker run "ThreadPoolExecutor.java" 628]

isak 2020-10-14T23:02:46.428100Z

This is on windows. (The describe response looks to be correct already, because I'm able to invoke.)