reblocks icon indicating copy to clipboard operation
reblocks copied to clipboard

Calling (update mywidget) from a new thread

Open bamboospirit opened this issue 4 years ago • 2 comments

How to make a new thread aware of the session it was created from ?

(:input :type "button" :value "Add random task (with (update) called from a different thread)" :onclick
		  (weblocks/actions:make-js-action
		   (lambda (&rest args )
		     (add-task task-list (format nil "~A" (random 1001)))
		     (bt:make-thread
		      (lambda ()
			(weblocks/dependencies:with-collected-dependencies 
			  (sleep 0.5)
			  (update task-list) ; ERROR: Session was not created for this request!
			  ))))))

complete executable code to illustrate the problem: https://gist.github.com/bamboospirit/e6ad95503ec40d2c7649f4aa14ad4979#file-thr-update-lisp

bamboospirit avatar Jan 01 '21 12:01 bamboospirit

There are two problems with this code.

To make the session variable available in the new thread, you need to provide initial bindings to a new thread like that:

CL-USER> (let ((weblocks/session::*session* :test-value))
           (bt:make-thread (lambda ()
                             (format t "Session in thread: ~A~%"
                                     weblocks/session::*session*))))
Session in thread: NIL

but

CL-USER> (let ((weblocks/session::*session* :test-value))
           (bt:make-thread (lambda ()
                             (format t "Session in thread: ~A~%"
                                     weblocks/session::*session*))
                           :initial-bindings
                           (list* (cons 'weblocks/session::*session*
                                        weblocks/session::*session*)
                                  bt:*default-special-bindings*)))
Session in thread: TEST-VALUE

However, this will not solve the second issue:

When you'll call the update method in the thread, it will have no effect, because Weblocks already sent a response to the browser.

When you call to action and update is called the thread which processes the HTTP request, then a HTML with a new widget representation is sent in response to the action. With update in a separate thread, this will not work, because you need an additional channel to send an update to the client-side.

Currently, this task only can be done with a WebSocket.

svetlyak40wt avatar Jan 01 '21 12:01 svetlyak40wt

Got it. https://github.com/40ants/weblocks-websocket did the job

bamboospirit avatar Jan 01 '21 14:01 bamboospirit