taoensso / sente

Realtime web comms library for Clojure/Script

Home Page:https://www.taoensso.com/sente

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add support for other Clojure-side web servers (i.e. besides http-kit)

ptaoussanis opened this issue · comments

This shouldn't be too hard (there's only a small surface area that actually interacts with http-kit) but will require potential servers to expose a sensible API that we can use.

Don't have a lot of time to look into this myself atm, so assistance would be welcome:

  • What server(s) should we target? This might be a useful starting point?
  • What API does each expose?
  • Suggested abstraction to encapsulate any API differences?

Otherwise any other thoughts/suggestions very welcome! Feel free to ping me with any questions :-)

The Jetty's would be a quick-hit I think:

Could do something similar to the clojure.tools.logging selection: https://github.com/clojure/tools.logging/blob/master/src/main/clojure/clojure/tools/logging/impl.clj

Maybe dynamically loading the relevant namespace if they're present, added as provided deps:
https://github.com/ToBeReplaced/jetty9-websockets-async
https://github.com/lynaghk/jetty7-websockets-async

It also wouldn't be unreasonable to require the user to select an impl when they start up sente, just the resolution has to be dynamic.

I'm working with jetty now, but I haven't tried sente yet because of this issue (Jetty's not really a req for me, just haven't bothered with http-kit).

Hi Gary,

I'm interested in adding support for other servers, but I'll be honest in saying it's not a major priority atm. Am in the middle of a couple product launches atm, so time's pretty limited and I've got a lot of other big improvements I'd still like to make.

First step in supporting other servers would be to define a protocol that servers could implement. I'm not familiar with the async + WebSocket capabilities of things like Jetty, so would need to do a little digging first to find out what kind of interface they'd be capable of implementing.

Would also need to test that Jetty & co. are actually capable of handling the high-concurrency workloads necessary for something like Sente. Http-kit's exceptionally efficient at workloads like this.

So yeah, it's definitely on the cards - just realistically not something I'm going to have real time to investigate myself seriously soon.

Have removed the "pull-requests welcome!" label until I've handled my end in abstracting the http server interface.

Here's another candidate, I believe:
https://github.com/mpenet/jet

commented

Undertow support would be nice. Specially with the ring adapter and websocket support in place.
http://undertow.io/documentation/core/websockets.html
https://github.com/piranha/ring-undertow-adapter

I've done some work on creating a Channel abstraction for Sente, and
using that abstraction to support both http-kit and Immutant 2. I
realize you removed the 'pull-requests-welcome!' tag, but I'm hoping
we can have a discussion about my implementation, and see what it
would take to get it (or something similar merged in).

The full PR is #101.

The real changes are in interfaces.cljx and both namespaces in
sente/server/. The changes to sente.cljx to use the Channel
procotol are extensive, but should result in no behavioral changes (as
far as I can tell from playing with the example app). I tested with
http-kit, Immutant embedded (which uses undertow directly), and
deploying an Immutant war to the WildFly application server (which
uses servlets inside undertow).

The differences between the new Sente Channel protocol and http-kit's
Channel protocol are:

  • with-channel has been replaced with as-channel, which is a
    function that takes callbacks instead of a macro that binds the
    channel to a symbol. In http-kit's case, the channel is already
    available when with-channel starts to evaluate its body, but
    Immutant cannot provide that same mechanism, but instead passes the
    channel to an on-open callback when it is ready. Sente's
    as-channel adopts that same approach, and the http-kit
    implementation uses with-channel, and just calls the on-open
    immediately.
  • send! no longer closes http streams automatically - you have to
    explicitly pass a truthy value for the close? parameter.

The as-channel function isn't part of a protocol, since there are no
objects that directly represent a running server (starting an http-kit
server returns a stop function, starting an Immutant server returns a
map). Instead, as-channel is a regular function with a default
implementation that throws. Implementations (currently in
servers/http_kit.clj and servers/immutant.clj) alter the var root
of as-channel (via provide-as-channel!) with a function that does
the correct thing for that particular server. sente.cljx requires
both of these namespaces, but they are guarded by the with-import
macro to only code that will work based on which server is currently
on the classpath.

Other changes include:

  • the IAsyncHTTPServer was removed, since it's not used by this
    implementation
  • the dependence on http-kit was removed from project.clj. Users
    would be responsible for having a recent enough http-kit dependency
    in their own application.
  • the example application has been modified to use either Immutant or
    http-kit, just by adjusting commented lines in project.clj and
    my_app.cljx.

I haven't looked at what it would take to support any other servers
(Jetty, etc), but hopefully the protocol is general enough to be
adapted to them.

This is a first cut at solving this problem, I'm happy do discuss it
and make any changes necessary to have this be part of the next Sente
release. I updated the docstrings in sente.cljx to reflect these
changes, but haven't yet made any changes to the README.

And if you would prefer to have channel abstraction and the Immutant
implementation as separate PR's, I can do that as well.

I forgot to mention that this depends on an Immutant API that isn't yet in an official release, only incremental builds, so it may change some before a release. If the API does change, it should only affect servers/immutant.clj.

Closing here since we can continue any Immutant discussion at #101 and I've since added #102 for any other servers.

Busy working on a merge for #101.