Skip to content

Commit

Permalink
Rejigger things to be more testable to facilitate #8.
Browse files Browse the repository at this point in the history
  • Loading branch information
gphat committed Feb 5, 2014
1 parent 78377ef commit 2da33e5
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 74 deletions.
89 changes: 36 additions & 53 deletions src/main/scala/io/keen/client/scala/Client.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package io.keen.client.scala

import com.ning.http.client.Response
import dispatch._
import Defaults._
import dispatch.{Http,Req,url}

import grizzled.slf4j.Logging
import java.net.URL
import scala.concurrent.Promise
import scala.concurrent.Future
import java.nio.charset.StandardCharsets

// XXX Remaining: Extraction, Funnel, Saved Queries List, Saved Queries Row, Saved Queries Row Result
Expand All @@ -17,7 +16,8 @@ class Client(
projectId: String,
masterKey: String,
writeKey: String,
readKey: String) extends Logging {
readKey: String,
httpAdapter: HttpAdapter = new HttpAdapter()) extends Logging {

/**
* Publish a single event. See [[https://keen.io/docs/api/reference/#event-collection-resource Event Collection Resource]].
Expand All @@ -28,7 +28,7 @@ class Client(
def addEvent(collection: String, event: String): Future[Response] = {
val freq = (url(apiURL) / version / "projects" / projectId / "events" / collection).secure
.setBody(event.getBytes(StandardCharsets.UTF_8))
doRequest(freq.POST, writeKey)
httpAdapter.doRequest(freq.POST, writeKey)
}

/**
Expand All @@ -39,7 +39,7 @@ class Client(
def addEvents(events: String): Future[Response] = {
val freq = (url(apiURL) / version / "projects" / projectId / "events").secure
.setBody(events.getBytes(StandardCharsets.UTF_8))
doRequest(freq.POST, writeKey)
httpAdapter.doRequest(freq.POST, writeKey)
}

/**
Expand Down Expand Up @@ -81,7 +81,7 @@ class Client(
filters: Option[String] = None,
timeframe: Option[String] = None,
timezone: Option[String] = None,
groupBy: Option[String]= None): Future[Response] = {
groupBy: Option[String]= None): Future[Response] =

doQuery(
analysisType = "count",
Expand All @@ -91,7 +91,6 @@ class Client(
timeframe = timeframe,
timezone = timezone,
groupBy = groupBy)
}

/**
* Returns the number of '''unique''' resources in the event collection matching the given criteria. See [[https://keen.io/docs/api/reference/#event-resource Event Resource]].
Expand All @@ -109,7 +108,7 @@ class Client(
filters: Option[String] = None,
timeframe: Option[String] = None,
timezone: Option[String] = None,
groupBy: Option[String]= None): Future[Response] = {
groupBy: Option[String]= None): Future[Response] =

doQuery(
analysisType = "count",
Expand All @@ -119,7 +118,6 @@ class Client(
timeframe = timeframe,
timezone = timezone,
groupBy = groupBy)
}

/**
* Returns the maximum numeric value for the target property in the event collection matching the given criteria. See [[https://keen.io/docs/api/reference/#maximum-resource Maximum Resource]].
Expand Down Expand Up @@ -191,7 +189,7 @@ class Client(
filters: Option[String] = None,
timeframe: Option[String] = None,
timezone: Option[String] = None,
groupBy: Option[String]= None): Future[Response] = {
groupBy: Option[String]= None): Future[Response] =

doQuery(
analysisType = "select_unique",
Expand All @@ -201,7 +199,6 @@ class Client(
timeframe = timeframe,
timezone = timezone,
groupBy = groupBy)
}

/**
* Returns the sum across all numeric values for the target property in the event collection matching the given criteria. See [[https://keen.io/docs/api/reference/#sum-resource Sum Resource]].
Expand Down Expand Up @@ -237,15 +234,15 @@ class Client(
*/
def deleteCollection(collection: String): Future[Response] = {
val freq = (url(apiURL) / version / "projects" / projectId / "events" / collection).secure
doRequest(freq.DELETE, masterKey)
httpAdapter.doRequest(freq.DELETE, masterKey)
}

/**
* Removes a property and deletes all values stored with that property name. See [[https://keen.io/docs/api/reference/#property-resource Property Resource]].
*/
def deleteProperty(collection: String, name: String): Future[Response] = {
val freq = (url(apiURL) / version / "projects" / projectId / "events" / collection / "properties" / name).secure
doRequest(freq.DELETE, masterKey)
httpAdapter.doRequest(freq.DELETE, masterKey)
}

/**
Expand All @@ -255,7 +252,7 @@ class Client(
*/
def getEvents: Future[Response] = {
val freq = (url(apiURL) / version / "projects" / projectId / "events").secure
doRequest(freq.GET, masterKey)
httpAdapter.doRequest(freq.GET, masterKey)
}

/**
Expand All @@ -266,7 +263,7 @@ class Client(
*/
def getCollection(collection: String): Future[Response] = {
val freq = (url(apiURL) / version / "projects" / projectId / "events" / collection).secure
doRequest(freq.GET, masterKey)
httpAdapter.doRequest(freq.GET, masterKey)
}

/**
Expand All @@ -275,7 +272,7 @@ class Client(
*/
def getProjects: Future[Response] = {
val freq = (url(apiURL) / version / "projects").secure
doRequest(freq.GET, masterKey)
httpAdapter.doRequest(freq.GET, masterKey)
}

/**
Expand All @@ -284,15 +281,15 @@ class Client(
*/
def getProject: Future[Response] = {
val freq = (url(apiURL) / version / "projects" / projectId).secure
doRequest(freq.GET, masterKey)
httpAdapter.doRequest(freq.GET, masterKey)
}

/**
* Returns the property name, type, and a link to sub-resources. See [[https://keen.io/docs/api/reference/#property-resource Property Resource]].
*/
def getProperty(collection: String, name: String): Future[Response] = {
val freq = (url(apiURL) / version / "projects" / projectId / "events" / collection / "properties" / name).secure
doRequest(freq.GET, masterKey)
httpAdapter.doRequest(freq.GET, masterKey)
}

/**
Expand All @@ -301,26 +298,7 @@ class Client(
*/
def getQueries: Future[Response] = {
val freq = (url(apiURL) / version / "projects" / projectId / "queries").secure
doRequest(freq.GET, masterKey)
}

private def doQuery(
analysisType: String,
collection: String,
targetProperty: Option[String],
filters: Option[String] = None,
timeframe: Option[String] = None,
timezone: Option[String] = None,
groupBy: Option[String]= None): Future[Response] = {

val req = (url(apiURL) / version / "projects" / projectId / "queries" / analysisType).secure
.addQueryParameter("event_collection", collection)

val paramNames = List("target_property", "filters", "timeframe", "timezone", "group_by")
val params = List(targetProperty, filters, timeframe, timezone, groupBy)

val reqWithParams = parameterizeUrl(req, paramNames, params)
doRequest(reqWithParams.GET, readKey)
httpAdapter.doRequest(freq.GET, masterKey)
}

/**
Expand All @@ -343,23 +321,28 @@ class Client(
.foldLeft(req)((r, nameAndParam) => r.addQueryParameter(nameAndParam._1, nameAndParam._2.get))
}

/**
* Perform the request with some debugging for good measure.
*
* @param req The request
*/
private def doRequest(req: Req, key: String) = {
val breq = req.toRequest
debug("%s: %s".format(breq.getMethod, breq.getUrl))
Http(
req.setHeader("Content-type", "application/json; charset=utf-8")
// Set the provided key, for authentication.
.setHeader("Authorization", key)
)
private def doQuery(
analysisType: String,
collection: String,
targetProperty: Option[String],
filters: Option[String] = None,
timeframe: Option[String] = None,
timezone: Option[String] = None,
groupBy: Option[String]= None): Future[Response] = {

val req = (url(apiURL) / version / "projects" / projectId / "queries" / analysisType).secure
.addQueryParameter("event_collection", collection)

val paramNames = List("target_property", "filters", "timeframe", "timezone", "group_by")
val params = List(targetProperty, filters, timeframe, timezone, groupBy)

val reqWithParams = parameterizeUrl(req, paramNames, params)
httpAdapter.doRequest(reqWithParams.GET, readKey)
}
}

object Client {

/**
* Disconnects any remaining connections. Both idle and active. If you are accessing
* Keen through a proxy that keeps connections alive this is useful.
Expand Down
25 changes: 25 additions & 0 deletions src/main/scala/io/keen/client/scala/HttpAdapter.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.keen.client.scala

import dispatch._
import grizzled.slf4j.Logging
import scala.concurrent.ExecutionContext.Implicits.global

class HttpAdapter() extends Logging {

/**
* Perform the request with some debugging for good measure.
*
* @param req The request
*/
def doRequest(req: Req, key: String): Future[Response] = {
val breq = req.toRequest
debug("%s: %s".format(breq.getMethod, breq.getUrl))
Http(
req.setHeader("Content-type", "application/json; charset=utf-8")
// Set the provided key, for authentication.
.setHeader("Authorization", key)
) map { res =>
Response(statusCode = res.getStatusCode, body =res.getResponseBody)
}
}
}
6 changes: 6 additions & 0 deletions src/main/scala/io/keen/client/scala/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.keen.client

package object scala {

case class Response(statusCode: Int, body: String)
}
Loading

0 comments on commit 2da33e5

Please sign in to comment.