Special variable in hunchentoot
Asked Answered
P

1

7

Currently, I'm developing 2 web-based tools for my own need with hunchentoot.
Before starting hunchentoot, I want to set some special variable with let so there values will be available while hunchentoot is running.

Like :

(let ((*db-path* "my-db-file"))
  (start-hunchentoot))

But, once the handlers get invoiced, they don't seam to be in the let anymore and db-path falls back to its global state (which is nil).

At the moment I'm resolving this by writing the let in every handler.
But, I want a more general approach so I will be able to run both applications with different db-path in one run-time.

Is it possible to set db-path in a way so it will be valid for one instance of hunchentoot and not the other?

The used environment is SBCL 1.2.4 on Debian Jessie.

Pennyworth answered 22/10, 2016 at 9:33 Comment(2)
It would be better to have a class for the application with slots for the database/other configuration.Absorptivity
Right now I use a with macro but a class sounds more reasonable.Pennyworth
B
8

Around method

Adding db-path as a slot in the acceptor might be a suitable option. However, you can also write an around method for handle-request. Assuming *my-acceptor* is globally bound:

(defmethod hunchentoot:handle-request :around ((acceptor (eql *my-acceptor*)) request)
  (let ((*db-path* "my-db-file"))
    (call-next-method)))

Of course, you don't need to specialize with EQL, you can define your own subclass instead. The advantage of an around method over storing a configuration variable in the class instance is that you keep the benefits of using special variables, i.e. bindings are visible from everywhere in the dynamic scope. Here is what the documentation string, visible on Lispdoc, says about handle-request (emphasis mine):

This function is called once the request has been read and a REQUEST object has been created. Its job is to actually handle the request, i.e. to return something to the client.

Might be a good place for around methods specialized for your subclass of ACCEPTOR which bind or rebind special variables which can then be accessed by your handlers.

I encourage you to read Hunchentoot's documentation.

Special variables and threads

The behavior you observe is because:

  • The server is running in another thread.
  • Dynamic bindings are local to each thread, as explained in the manual:

    The interaction of special variables with multiple threads is mostly as one would expect, with behaviour very similar to other implementations.

    • global special values are visible across all threads;
    • bindings (e.g. using LET) are local to the thread;
    • threads do not inherit dynamic bindings from the parent thread

If you make your own threads, you can build a closure which binds variables as you want. You can also rely on the portable bordeaux-threads library which takes a list of bindings to be effective inside a thread.

Behrens answered 22/10, 2016 at 11:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.