Skip to content

A Basilisp Clojure async nREPL server for cooperative multitasking

License

Notifications You must be signed in to change notification settings

ikappaki/basilisp-nrepl-async

Repository files navigation

PyPI CI

Basilisp nREPL Server with Support for Cooperative Multitasking

Basilisp is a Python-based Lisp implementation that offers broad compatibility with Clojure. Refer to documentation for more details.

Overview

An nREPL server is a networked REPL for Clojure that facilitates remote code evaluation, code completion, and debugging within Clojure-enabled editors like Emacs (via CIDER) and VS Code (via Calva), among others.

This package provides an nREPL server implementation for Basilisp Clojure, evolved from the basilisp.contrib.nrepl-server namespace in Basilisp, addressing issues that arise from serving nREPL request in parallel with the main event loop.

Serving an nREPL client connection on a parallel thread in Python may conflict with the Global Interpreter Lock (GIL) and single-threaded libraries, potentially causing errors or crashes.

To mitigate this, the library includes an asynchronous mode where client requests are queued, allowing the main application to process them at a designated time within its main event loop. This is in addition to the synchronous multi-threaded mode, where client requests are handled immediately upon arrival.

Installation

To install basilisp-nrepl-async, run:

pip install basilisp-nrepl-async

Usage

See API.md.

Synchronous mode

To start in synchronous mode, call server-start! with the optional :host, :port and :nrepl-port-file keys. The server will block and handle client requests as they arrive.

(require '[basilisp-nrepl-async.nrepl-server :as nr])

(def server-async (nr/server-start! {:port 9999}))
; nREPL server started on port 9999 on host 127.0.0.1 - nrepl://127.0.0.1:9999

Asynchronous mode

To start the nREPL server on a random port bound to the local interface in asynchronous mode, call server-start! with the async? option set to true. Periodically invoke the returned work-fn within your program's main loop to handle client requests. Use the shutdown-fn to stop the server.

(require '[basilisp-nrepl-async.nrepl-server :as nr])
(import time)

;; Start the nREPL server on a separate thread to handle client
;; requests asynchronously
(def server-async (nr/server-start! {:async? true}))
; nREPL server started on port 55144 on host 127.0.0.1 - nrepl://127.0.0.1:55144

;; Process client requests on this thread
(let [{:keys [host port shutdown-fn work-fn]} server-async]
  (loop [] ;; suppose this is the main event loop

    (work-fn) ;; Execute any pending nREPL client work

    ;; simulate some work
    (time/sleep 0.5)

    (recur)))

The server will create an .nrepl-port file in the current working directory with the port number, which nREPL-enabled Clojure editors can use to connect.

You can also pass additional options to the server-start! function, such as :host, :port and :nrepl-port-file, to explicitly configure the server's listening interface, port, and the file where the port number is written (typically <your-basilisp-lib>/.nrepl-port for integration with your editor).

Development and Testing

To run the test suite, use the following command:

basilsp test

License

This project is licensed under the Eclipse Public License 2.0. See the LICENSE file for details.

Acknowledgments

This library is a spin-off of basilisp-blender's basilisp-blender.nrepl-server namespace.

About

A Basilisp Clojure async nREPL server for cooperative multitasking

Resources

License

Stars

Watchers

Forks

Packages

No packages published