Skip to content

Commit

Permalink
Set an optional Redis client to cache Klout API responses (recommende…
Browse files Browse the repository at this point in the history
…d for resolving user identities)
  • Loading branch information
Pierre-Elie Fauche committed Sep 16, 2012
1 parent 052f248 commit 809c4d7
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 28 deletions.
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "coffee_klout",
"description": "Klout API v2 wrapper, Coffee style.",
"version": "0.0.1",
"version": "0.0.9",
"author": "Pierre-Élie Fauché <[email protected]>",
"homepage": "https://github.com/pierreliefauche/coffee_klout",
"engines": {
Expand All @@ -25,7 +25,6 @@
"url": "git://github.com/pierreliefauche/coffee_klout.git"
},
"dependencies": {
"request": ">=2.11.1",
"underscore": ">=1.3.3"
"request": ">=2.11.1"
}
}
87 changes: 62 additions & 25 deletions src/index.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,76 @@ request = require "request"
# Klout API wrapper.
# Only v2.
# Only JSON.
# Only Redis.
class Klout
baseUri: "http://api.klout.com/v2"

# Create a Klout API v2 wrapper
#
# key - String Klout API key. (Required)
# options - Hash
# key - String Klout API key. (Required)
# cacheClient - Object Configured Redis client, ready to use (Optional)
# cacheLifetime - Integer TTL for storing API responses (other than identities) in cache (Optional)
#
# If a Redis client is provided, all calls to resolve
# identities will be cached (TTL set to several years)
# If a cache lifetime is provided, other API calls will
# also be cached for the time specified (will not affect
# identities cache TTL)
#
# Returns a Klout instance
constructor: (@key)->
@baseUri = "http://api.klout.com/v2"
constructor: (options)->
@key = options.key
@cache = options.cacheClient
@cacheLifetime = options.cacheLifetime

# Fetch an object from cache, if a cache is configured
_getFromCache: (key, callback)->
return callback "No cache set" unless @cache
@cache.get key, (error, result)->
return callback error or 'No cached value' if error or not result
callback null, JSON.parse(result)

# Set an object in cache, if a cache is configured
_setInCache: (key, value, ttl, callback)->
return callback "No cache set" unless @cache
@cache.set key, JSON.stringify(value), (error)=>
callback error
@cache.expire key, ttl if ttl and not error

# Make a GET request to the Klout API
#
# resource - String uri of the requested data, does not include hostname
# cacheTTL - Integer lifetime of the response in cache (response won’t be cached if absent)
# callback - Function called on success/error
_get: (resource, callback)->
_get: (resource, cacheTTL, callback)->
return unless callback

# API key is always required
auth = "#{if ~resource.indexOf('?') then '&' else '?'}key=#{@key}"

request @baseUri + resource + auth, (error, response, body)->
return callback error if error
switch response.statusCode
when 401 then callback new Error("Invalid authentication credentials.")
when 403 then callback new Error("Inactive key, or call threshold reached.")
when 404 then callback new Error("Resource or user not found.")
when 500 then callback new Error("Klout internal server error.")
when 502 then callback new Error("Klout is down or being upgraded.")
when 503 then callback new Error("Klout is unavailable.")
else
try
callback null, JSON.parse(body)
catch ex
callback ex
# Check cache
@_getFromCache resource, (error, result)=>
return callback null, result unless error

# Cache empty or not configured, so execute the request

# API key is always required
auth = "#{if ~resource.indexOf('?') then '&' else '?'}key=#{@key}"
console.log 'will request', resource
request @baseUri + resource + auth, (error, response, body)=>
return callback error if error
switch response.statusCode
when 401 then callback new Error("Invalid authentication credentials.")
when 403 then callback new Error("Inactive key, or call threshold reached.")
when 404 then callback new Error("Resource or user not found.")
when 500 then callback new Error("Klout internal server error.")
when 502 then callback new Error("Klout is down or being upgraded.")
when 503 then callback new Error("Klout is unavailable.")
else
try
data = JSON.parse(body)
callback null, data
@_setInCache resource, data, cacheTTL, (->) if cacheTTL
catch ex
callback ex

# Get the Klout identity of a user (basically his Klout ID)
# based on his ID on a different network
Expand Down Expand Up @@ -64,7 +100,8 @@ class Klout
else if options["klout_id"]
path = "/klout/#{options["klout_id"]}"

@_get "/identity.json#{path}", callback if path
# 10 Years = an eternity of cache, as Klout suggests
@_get "/identity.json#{path}", 315576000, callback if path

# Helper to abstract the call to getKloutIdentity to get the user’s Klout ID
#
Expand All @@ -74,14 +111,14 @@ class Klout
_getUserResource: (userId, resource, callback)->
return unless callback

userId = 'klout_id': user unless typeof userId is 'object'
userId = 'klout_id': userId unless typeof userId is 'object'

if userId['klout_id']
@_get resource.replace(':kloutId', userId['klout_id']), callback
@_get resource.replace(':kloutId', userId['klout_id']), @cacheLifetime, callback
else
@getKloutIdentity userId, (error, identity)=>
return callback error if error
@_get resource.replace(':kloutId', identity.id), callback
@_get resource.replace(':kloutId', identity.id), @cacheLifetime, callback

# Following methods reflect Klout API methods
# http://klout.com/s/developers/v2
Expand Down

0 comments on commit 809c4d7

Please sign in to comment.