Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #2 from cloudfoundry-samples/redis

Fixed the issue by making it a rack app and pointing to the prod vmc beta gem
  • Loading branch information...
commit cf41854c666d590b414fc3c9bc9ed736fe59cbef 2 parents 33c0b99 + 142db29
@ciberch ciberch authored
View
10 Gemfile
@@ -5,4 +5,12 @@ gem "ruby-hmac"
gem "json"
gem "haml"
gem "hashie"
-gem "emk-sinatra-url-for"
+gem "emk-sinatra-url-for"
+
+gem "logger"
+gem "redis"
+gem "cloudfoundry-env","~> 0.0.5", :require => "cloudfoundry/environment"
+
+group :development do
+ gem "vmc", "~> 0.3.16.beta.5"
+end
View
25 Gemfile.lock
@@ -1,28 +1,53 @@
GEM
remote: http://rubygems.org/
specs:
+ addressable (2.2.7)
+ cloudfoundry-env (0.0.5)
+ hashie
emk-sinatra-url-for (0.2.1)
sinatra (>= 0.9.1.1)
haml (3.1.4)
hashie (1.2.0)
+ interact (0.4.2)
json (1.6.6)
+ json_pure (1.6.6)
+ logger (1.2.8)
+ mime-types (1.18)
rack (1.4.1)
rack-protection (1.2.0)
rack
+ redis (2.2.2)
+ rest-client (1.6.7)
+ mime-types (>= 1.16)
ruby-hmac (0.4.0)
+ rubyzip (0.9.6.1)
sinatra (1.3.2)
rack (~> 1.3, >= 1.3.6)
rack-protection (~> 1.2)
tilt (~> 1.3, >= 1.3.3)
+ terminal-table (1.4.5)
tilt (1.3.3)
+ uuidtools (2.1.2)
+ vmc (0.3.16.beta.5)
+ addressable (~> 2.2.6)
+ interact (~> 0.4.0)
+ json_pure (>= 1.5.1, < 1.7.0)
+ rest-client (>= 1.6.1, < 1.7.0)
+ rubyzip (~> 0.9.4)
+ terminal-table (~> 1.4.2)
+ uuidtools (~> 2.1.0)
PLATFORMS
ruby
DEPENDENCIES
+ cloudfoundry-env (~> 0.0.5)
emk-sinatra-url-for
haml
hashie
json
+ logger
+ redis
ruby-hmac
sinatra
+ vmc (~> 0.3.16.beta.5)
View
3  config.ru
@@ -0,0 +1,3 @@
+require './jobs'
+
+run SummerJobsApp
View
1  config/cloudfoundry.yml
@@ -0,0 +1 @@
+autoconfig: false
View
132 jobs.rb
@@ -1,63 +1,105 @@
-require "sinatra"
+require "sinatra/base"
require "json"
require "hashie/mash"
require "sinatra/url_for"
+require "cloudfoundry/environment"
+require "redis"
+require "logger"
+
require_relative "lib/DOLDataSDK"
-helpers do
-
- def get_jobs(query='vmware')
- @jobs = []
- page = params['page'].to_i || 1
- page = 1 if page < 1
- options = {:format => "'json'", :query => "'#{query}'", :region => "", :locality => "", :skipCount => 1 + (10 * (page-1))}
-
- @dol_request.call_api('SummerJobs/getJobsListing', options) do |results, error|
- if error
- puts error
- else
- results.each do |n|
- n['pagemap']['jobposting'].each_with_index do |job, i|
- job[:url] = n['pagemap']['article'][i]['url'] rescue n['link']
- @jobs << Hashie::Mash.new(job)
+class AppConfig
+ class << self
+ attr_accessor :logger
+ end
+end
+
+AppConfig.logger = Logger.new(STDOUT)
+
+class SummerJobsApp < Sinatra::Base
+ LOCAL_REDIS = {host: "127.0.0.1", port: "6379"}
+
+ helpers Sinatra::UrlForHelper
+
+ def initialize
+ super
+
+ @logger = AppConfig.logger
+ @redis = Redis.new(CloudFoundry::Environment.redis_cnx || LOCAL_REDIS)
+ @logger.info("REDIS CONFIGURED")
+
+ begin
+ @redis.ping #will raise exception ==> good so we can fail fast
+ @logger.info("REDIS is UP")
+ rescue
+ @logger.error("REDIS is NOT RUNNING")
+ @redis = nil
+ end
+ end
+
+ helpers do
+
+ def get_jobs(query='vmware')
+ @jobs = []
+ page = params['page'].to_i || 1
+ page = 1 if page < 1
+ options = {:format => "'json'", :query => "'#{query}'", :region => "", :locality => "", :skipCount => 1 + (10 * (page-1))}
+
+ @dol_request.call_api('SummerJobs/getJobsListing', options) do |results, error|
+ if error
+ @logger.error(error)
+ else
+ results.each do |n|
+ n['pagemap']['jobposting'].each_with_index do |job, i|
+ job[:url] = n['pagemap']['article'][i]['url'] rescue n['link']
+ @jobs << Hashie::Mash.new(job)
+ end
end
end
end
+ @dol_request.wait_until_finished
+ @jobs
end
- @dol_request.wait_until_finished
- @jobs
+
end
-end
+ before do
+ @appid = ENV['facebook_app_id']
+ @description = "A new call-to-action for businesses, non-profits, and government to provide pathways to employment for low-income and disconnected youth in the summer of 2012"
+ @context = DOL::DataContext.new('http://api.dol.gov', ENV['usdol_token'], ENV['usdol_secret'])
+ @dol_request = DOL::DataRequest.new(@context)
+ @dol_request.redis = @redis
+ end
-before do
- @appid = ENV['facebook_app_id']
- @description = "A new call-to-action for businesses, non-profits, and government to provide pathways to employment for low-income and disconnected youth in the summer of 2012"
- @context = DOL::DataContext.new('http://api.dol.gov', ENV['usdol_token'], ENV['usdol_secret'])
- @dol_request = DOL::DataRequest.new(@context)
-end
+ get "/" do
+ @jobs = get_jobs()
-get "/" do
- @jobs = get_jobs()
+ @full_url = url_for("/", :full)
+ @image = url_for("/images/me.png", :full)
+ @title = "Summer Jobs+ 2012"
+ haml :index
+ end
- @full_url = url_for("/", :full)
- @image = url_for("/images/me.png", :full)
- @title = "Summer Jobs+ 2012"
- haml :index
-end
+ get "/search" do
+ @full_url = url_for("/search", :full)
+ @title = "Search results for #{params['q']}"
+ @jobs = get_jobs(params['q'])
+ haml :index
+ end
-get "/search" do
- @full_url = url_for("/search", :full)
- @title = "Search results for #{params['q']}"
- @jobs = get_jobs(params['q'])
- haml :index
-end
+ get "/search.json" do
+ @full_url = url_for("/search", :full)
+ @title = "Search results for #{params['q']}"
+ @jobs = get_jobs(params['q'])
+ @jobs.to_json
+ end
-get "/search.json" do
- @full_url = url_for("/search", :full)
- @title = "Search results for #{params['q']}"
- @jobs = get_jobs(params['q'])
- @jobs.to_json
-end
+ # Eager loads the app to prefetch the blog
+ prototype
+
+ run! if __FILE__ == $0
+end
+# Hack would be nice if this got fixed
+#require 'sinatra'
View
92 lib/DOLDataSDK.rb
@@ -30,7 +30,7 @@ def valid?
# that provides the DatRequest with a host, API key and SharedSecret.
# After generating a request, call #call_api to submit it.
class DataRequest
- attr_accessor :context
+ attr_accessor :context, :redis
def initialize context
@context = context
@@ -60,44 +60,65 @@ def call_api method, arguments = {}, &block
url = get_url(method, arguments)
timestamp = DOL.timestamp
+ redis_key = redis_cache_key(url)
+
# Creates a new thread, creates an authenticated request, and requests data from the host
@mutex.synchronize do
- @active_requests << Thread.new do
- request = Net::HTTP::Get.new [url.path, url.query].join '?'
- header = get_header(url,timestamp)
- request.add_field 'Authorization', header
- request.add_field 'Accept', 'application/json'
-
- result = Net::HTTP.start(url.host, url.port) do |http|
- http.request request
- end
+ @active_requests << Thread.new do
+ clean = nil
- if result.is_a? Net::HTTPSuccess
- clean = result.body.gsub(/\\+"/, '"')
- clean = clean.gsub /\\+n/, ""
- clean = clean.gsub /\"\"\{/, "{"
- clean = clean.gsub /}\"\"/, "}"
- #clean = clean.gsub /\\\\u/, "\u"
- #puts clean
-
- result = []
- begin
- result = JSON.parse(clean)
- result = result['d']['getJobsListing']['items']
- rescue Exception => ex
- puts "Invalid format for #{clean} got error parsing it #{ex}"
- end
- block.call result, nil
- else
- puts result.inspect
- block.call nil, "Error: #{result.message}"
- end
+ if @redis and @redis.exists(redis_key)
+ clean = @redis.get(redis_key)
+ end
- @mutex.synchronize do
- @active_requests.delete Thread.current
+ unless clean
+ request = Net::HTTP::Get.new [url.path, url.query].join '?'
+ header = get_header(url,timestamp)
+ request.add_field 'Authorization', header
+ request.add_field 'Accept', 'application/json'
+
+ result = Net::HTTP.start(url.host, url.port) do |http|
+ http.request request
+ end
+
+ if result.is_a? Net::HTTPSuccess
+ clean = result.body.gsub(/\\+"/, '"')
+ clean = clean.gsub /\\+n/, ""
+ clean = clean.gsub /\"\"\{/, "{"
+ clean = clean.gsub /}\"\"/, "}"
+ #clean = clean.gsub /\\\\u/, "\u"
+ #puts clean
+
+ if @redis
+ @redis.set(redis_key, clean)
+ @redis.expire(redis_key, 60 * 15)
end
+
+ else
+ clean = nil
+ AppConfig.logger.error(result.inspect)
+ block.call nil, "Error: #{result.message}"
+ end
end
- end
+
+ result = []
+ begin
+ if clean
+ result = JSON.parse(clean)
+ result = result['d']['getJobsListing']['items']
+ end
+ rescue Exception => ex
+ AppConfig.logger.error("Invalid format for #{clean} got error parsing it #{ex}")
+ @redis.delete(redis_key) if @redis
+ end
+ block.call result, nil
+
+ @mutex.synchronize do
+ @active_requests.delete Thread.current
+ end
+ end
+ end
+
end
# Halts program until all ongoing requests sent by this DataRequest finish
@@ -126,6 +147,11 @@ def get_header(url, timestamp)
# Generates timestamp and url
"Timestamp=#{timestamp}&ApiKey=#{@context.key}&Signature=#{signature timestamp, url}"
end
+
+ def redis_cache_key(url)
+ [url.path, url.query].join '?'
+ end
+
end
def self.timestamp
View
21 manifest.yml
@@ -1,13 +1,16 @@
----
-applications:
- .:
+---
+applications:
+ .:
name: summerjobs
- framework:
- name: sinatra
- info:
- mem: 128M
- description: Sinatra Application
- exec: ruby jobs.rb
url: ${name}.${target-base}
+ framework:
+ name: rack
+ info:
+ mem: 128M
+ description: Rack Application
+ exec:
mem: 128M
instances: 1
+ services:
+ redis-www-cache:
+ type: redis
Please sign in to comment.
Something went wrong with that request. Please try again.