Closed amirouche closed 3 years ago
Your are totally right. Do you think using fibers
would work? That is, you give it a channel instead of a callback.
A callback is more general than a channel. With callback you can pass something like:
(redis-subscribe "topic" (lambda (obj) (put-message channel obj)))
Forcing to pass a channel is not necessary.
That is totally true. Alright, I'll see if I have time to add that. Thanks!
I set up something to get guile-redis subscribe
to behave like it does in Python redis module:
(use-modules (rnrs bytevectors))
(use-modules (ice-9 iconv))
(use-modules (ice-9 binary-ports))
(use-modules (ice-9 textual-ports))
(use-modules (ice-9 rdelim))
(use-modules (redis))
(define (redis-sock-get conn)
(let ((get-sock
(record-accessor
(record-type-descriptor conn)
(caddr (record-type-fields (record-type-descriptor conn))))))
(get-sock conn)))
(define (subscribe-listen redis-sock)
(let ((sub-buf (make-bytevector 1024)))
(recv! redis-sock sub-buf)
(display (read-delimited
"\0"
(open-input-string (bytevector->string sub-buf "utf8"))))
(newline)
(subscribe-listen redis-sock)))
;; (define conn (redis-connect #:host "127.0.0.1" #:port 6379))
;; (redis-send conn (subscribe '(soda-stuff)))
;; (define redis-socket (redis-sock-get conn))
;; (subscribe-listen redis-socket)
This way, it goes into a loop and reads bytes directly from the socket and sends them to a buffer. I had tried to make a recursive procedure to loop (redis-send)
to perform this behavior but found it used like 110% of the process CPU core. So I looked at Python redis and saw that they read the bytes right from the socket, so I did something like that.
Does that seem useful? If so, I can parameterize it better and clean up the code. I just started learning Scheme (and Lisp in general), so I'm not all that clear on the idiom--what should parameters for a procedure like that be? I was thinking it could take a connection and abstract the bit with obtaining the socket (that confused me a lot, the record datatype, did I do that right in using the record-accessor?). Then the other params, I suppose, should be a buffer to write the received message into, and then maybe a callback do so something with the specified buffer?
From there, I imagine one would do something asynchronous with the data. I'm trying to learn fibers, but I'm a librarian, not a hardcore CS person, so it's a bit of a steep learning curve--but really interesting to study.
I don't know exactly what I'm trying with this stuff, but I have a couple of ideas: I want to make a real-time collaborative note-taking app that's based on org-mode. Or a weird, text-based blogging-app that has a quasi-graphical interface based on ascii art (maybe a little like the Cypher language used by Neo4j graph DB).
Sorry for the rambling comment--just wanted to holler at my Guile people! Guile is for sure the most fun language to program in. If you like the subscribe-listen
procedure, I can clean it up and make a PR.
Hi @soda-hobart! Thank you for your message. With almost 1 year delay I'm now looking into this, sorry about that. I can only work on Guile at nights when I'm not too tired from work and kids and life in general. But it's great to hear you are a librarian and working on Guile! Really surprised (and happy) you chose Guile. May I ask why did you start working on Guile?
I'm playing around and see how to implement this. I'm leaning towards something like @amirouche suggested above.
This is now fixed in guile-redis 2.0.0.
I think there is a bug with publish, subscribe and related commands. Those are not mere request-reply commands. It seems to me the subscribe command should take a callback as argument.