Open hraban opened 2 months ago
I've never tried to execute IN-THREAD during the page initialization. Previously I did this inside the RENDER method.
However, if you are calling update
on counter-box
widget, it will cause creation of a new thread each time. To prevent this, wrap your in-thread
form with (unless reblocks-websocket:*background* (in-thread ...))
.
Ah, I was going off of the tutorial in the documentation here https://40ants.com/reblocks-websocket/ which has:
(defmethod initialize-instance ((instance counter-box) &rest restargs)
(declare (ignorable restargs))
(call-next-method)
(reblocks-websocket:in-thread ("Update counter")
(sleep 3)
;; Updating counter
(incf (counter instance))
(reblocks:update instance)))
I'm still not quite clear on where else to put the code. Everywhere I put it leads to either errors, deadlocks, concurrent hash access violations, etc. Do you maybe have a live example somewhere?
Try to move it to the RENDER method.
Great thanks, this is definitely an improvement.
~These also get triggered for async POSTs though--I guess that makes sense, but is there an easy way to only run code on the initial actual payload and not on async requests?~ found it.
Feel free to use this to update the docs for this package!
Current code:
(defpackage test
(:use #:cl
#:reblocks-ui/form
#:reblocks/html)
(:import-from #:reblocks-parenscript)
(:import-from #:reblocks/widget
#:render
#:update
#:defwidget)
(:import-from #:reblocks/app
#:defapp)
(:import-from #:reblocks-websocket
#:websocket-widget)
(:export #:main))
(in-package #:test)
(defapp page :prefix "/")
(defwidget counter-box (reblocks-websocket:websocket-widget)
((counter :initform 0
:accessor counter)))
(defmethod reblocks/page:init-page ((app page) (url-path string) expire-at)
(declare (ignorable app url-path expire-at))
(make-instance 'counter-box))
(defmethod render ((instance counter-box))
(unless (or reblocks-websocket:*background* (reblocks/request:ajax-request-p))
(reblocks-websocket:in-thread ("Update counter")
(sleep 3)
;; Updating counter
(incf (counter instance))
(update instance)))
(with-html
(:h1 "Counter: " (counter instance))
(with-html-form (:POST (lambda (&key btn &allow-other-keys)
(cond
((equal btn "+")
(incf (counter instance)))
((equal btn "-")
(decf (counter instance))))
(update instance)))
(:input :type :submit :name "btn" :value "+")
(:input :type :submit :name "btn" :value "-"))))
(defun main ()
(reblocks/server:start :port 4000))
I have create a small demo based off of the tutorial:
But on first page load I get this error:
I had a look in the guts of reblocks-websocket and it seems quite fundamental; you need the page to send updates, but this initializer is building that very same page. How do you break that cycle?¯