Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add wrappers for Finagle HTTP #4

Merged
merged 20 commits into from
Dec 18, 2014
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ pom.xml.asc
.lein-plugins/
.lein-failures
doc/codox
/.idea
*iml
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ If not, check out its [docs](https://twitter.github.io/finagle/guide/).

## Building

lein sub -s "lein-finagle-clojure:finagle-clojure-template:core:thrift" install
lein sub -s "lein-finagle-clojure:finagle-clojure-template:core:thrift:http" install


## Running Tests
Expand All @@ -21,6 +21,7 @@ The readmes in each sub-library have more information.

* `core`: convenience fns for interacting with Futures.
* `thrift`: create Thrift clients & servers.
* `http`: create HTTP servers, requests, and responses
* `lein-finagle-clojure`: a lein plugin for automatically compiling Thrift definitions using [Scrooge](https://twitter.github.io/scrooge/index.html).
* `finagle-clojure-template`: a lein template for creating new projects using finagle-clojure & Thrift.

Expand Down
1 change: 1 addition & 0 deletions core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ This module contains wrappers for `com.twitter.util.Future` & core Finagle class
* `finagle-clojure.futures`: wrappers around `Future` operations.
* `finagle-clojure.scala`: sugar for Clojure/Scala interop.
* `finagle-clojure.service`: wrappers for operations on `Service`.
* `finagle-clojure.server`: wrappers for creating, starting, and stopping `Server`s.
45 changes: 45 additions & 0 deletions core/src/finagle_clojure/options.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
(ns finagle-clojure.options
"Functions for working with `scala.Option` objects."
(:import (scala Option)))

(defn ^Option option
"Returns an Option with the given value `v`.

*Arguments*:

* `v`: the value that the new Option should be defined with.

*Returns*:

`Some(v)` if `v` is present and non-null, `None` otherwise"
([]
(Option/empty))
([v]
(Option/apply v)))

(defn empty? [^Option o]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the docstring for the empty? & get fns should come before the argument list, otherwise codox won't pick up the docstring.

"Does Option `o` have a value? Returns true if so, false otherwise.

*Arguments*:

* `o`: an Option

*Returns*:

true if `v` is None, false otherwise"
(.isEmpty o))

(defn get [^Option o]
"Returns the value wrapped by `o`.
Although the Scala implementation throws a `Predef.NoSuchElementException` if called
on an empty Option, Clojure generally avoids throwing on empty gets, instead preferring to return nil.
This function adopts the Clojure behavior, choosing to treat this effectively as a call to `getOrNull`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice, i like that this adapts the Scala interface into something more idiomatically Clojure

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, glad you like it. I'm on the fence about overriding get, though. I dislike overriding core functions in ways that alter their arity or semantics, but I don't like the idea of naming it oget or opt-get (or something) either. Thoughts?


*Arguments*:

* `o`: an Option

*Returns*:

the Option's value if non-empty, nil otherwise"
(when-not (empty? o) (.get o)))
152 changes: 152 additions & 0 deletions core/src/finagle_clojure/server.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
(ns finagle-clojure.server
"Functions for creating and altering `com.twitter.finagle.Server` objects independent
of any particular codec. To start an Http server specifically, see
`finagle-clojure.http.server/http-server`."
(:import (com.twitter.finagle.builder ServerBuilder Server)
(com.twitter.finagle Service)
(java.net InetSocketAddress)
(com.twitter.util Duration Future)
(com.twitter.finagle.tracing Tracer)
(com.twitter.finagle.stats StatsReceiver)))

(defn ^ServerBuilder builder
"A handy Builder for constructing Servers (i.e., binding Services to a port).
The `ServerBuilder` requires the definition of `codec`, `bind-to` and `named`.

The main class to use is [[com.twitter.finagle.builder.ServerBuilder]], as so:

```
(-> (builder)
(named \"servicename\")
(bind-to 3000)
(build some-service))
```

*Arguments*:

* None.

*Returns*:

a new instance of [[com.twitter.finagle.builder.ServerBuilder]]."
[]
(ServerBuilder/apply))

(defn ^Server build
"Given a completed `ServerBuilder` and a `Service`, constructs an `Server` which is capable of
responding to requests.

*Arguments*:

* `b`: a ServerBuilder
* `svc`: the Service this server will use to respond to requests

*Returns*:

a running instance of [[com.twitter.finagle.builder.Server]]"
[^ServerBuilder b ^Service svc]
(.unsafeBuild b svc))


;; TODO Does this belong more generically in a Closable namespace?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this is ok. not much else would be in a Closable ns, seems kinda heavyweight to require a ns for one fn

(defn ^Future close!
"Stops the given Server.

*Arguments*:

* `server`: an instance of [[com.twitter.finagle.builder.Server]]

*Returns*:

a Future that closes when the server stops"
[^Server server]
(.close server))

(defn ^ServerBuilder named
"Configures the given ServerBuilder with a name.

*Arguments*:

* `b`: a ServerBuilder
* `name`: the name of this server

*Returns*:

a named ServerBuilder"
[^ServerBuilder b ^String name]
(.name b name))

(defn ^ServerBuilder bind-to
"Configures the given ServerBuilder with a port.

*Arguments*:

* `b`: a ServerBuilder
* `p`: the port number to bind this server to

*Returns*:

a bound ServerBuilder"
[^ServerBuilder b p]
(.bindTo b (InetSocketAddress. (int p))))

(defn ^ServerBuilder request-timeout
"Configures the given ServerBuilder with a request timeout.

*Arguments*:

* `b`: a ServerBuilder
* `d`: the duration of the request timeout for this server

*Returns*:

a ServerBuilder configured with the given timeout"
[^ServerBuilder b ^Duration d]
(.requestTimeout b d))

(defn ^ServerBuilder codec
"Configures the given ServerBuilder with a codec.

*Arguments*:

* `b`: a ServerBuilder
* `cdc`: a Codec, CodecFactory, or Function1 that defines the server codec

*Returns*:

a ServerBuilder configured with the given codec"
[^ServerBuilder b cdc]
(.codec b cdc))

(defn max-concurrent-requests
"Configures the given ServerBuilder to accept a maximum number of concurrent requests."
[^ServerBuilder b mcr]
(.maxConcurrentRequests b (int mcr)))

(defn tracer
"Configures the given ServerBuilder to use a Tracer.

*Arguments*:

* `b`: a ServerBuilder
* `tracer`: a Tracer

*Returns*:

a ServerBuilder configured with the given tracer"
[^ServerBuilder b ^Tracer tracer]
(.tracer b tracer))

(defn report-to
"Configures the given ServerBuilder to report to a stats receiver.

*Arguments*:

* `b`: a ServerBuilder
* `rcvr`: a StatsReceiver

*Returns*:

a ServerBuilder configured with the given stats receiver"
[^ServerBuilder b ^StatsReceiver rcvr]
(.reportTo b rcvr))
21 changes: 21 additions & 0 deletions core/test/finagle_clojure/options_test.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
(ns finagle-clojure.options-test
(:refer-clojure :exclude [get empty?])
(:import (scala Some None$))
(:require [midje.sweet :refer :all]
[finagle-clojure.options :refer :all]))

(set! *warn-on-reflection* true)

(facts "option creation"
(class (option)) => None$
(class (option nil)) => None$
(class (option :foo)) => Some

(empty? (option)) => true
(empty? (option nil)) => true
(empty? (option :foo)) => false

(get (option)) => nil
(get (option nil)) => nil
(get (option :foo)) => :foo
)
9 changes: 9 additions & 0 deletions http/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/target
/classes
/checkouts
pom.xml
pom.xml.asc
*.jar
*.class
/.lein-*
/.nrepl-port
12 changes: 12 additions & 0 deletions http/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# http

This module contains wrappers for `com.twitter.finagle.HttpServer` and HTTP messages.

### Dependency

[finagle-clojure/http "0.1.2"]

### Namespaces

* `finagle-clojure.http.server`: a helper for building an HTTP server and a Clojured reference to the `Http` codec
* `finagle-clojure.http.message`: wrappers for creating `Response` and `Request` objects
13 changes: 13 additions & 0 deletions http/project.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
(defproject finagle-clojure/http "0.1.2-SNAPSHOT"
:description "A light wrapper around Finagle HTTP for Clojure"
:url "https://github.com/twitter/finagle-clojure"
:license {:name "Apache License, Version 2.0"
:url "https://www.apache.org/licenses/LICENSE-2.0"}
:scm {:name "git" :url "http://github.com/finagle/finagle-clojure"}
:plugins [[lein-midje "3.1.3"]]
:profiles {:test {:dependencies [[midje "1.6.3" :exclusions [org.clojure/clojure]]]}
:dev [:test {:dependencies [[org.clojure/clojure "1.6.0"]]}]
:1.5 {:dependencies [[org.clojure/clojure "1.5.1"]]}
:1.4 {:dependencies [[org.clojure/clojure "1.4.0"]]}}
:dependencies [[finagle-clojure/core "0.1.2-SNAPSHOT"]
[com.twitter/finagle-http_2.10 "6.18.0"]])
Loading