rack-campaign 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -1 +1,137 @@
1
- More to come soon...
1
+ h2. rack-campaign
2
+
3
+ This is a "Rack":http://rack.rubyforge.org/ application (a gem is available by the same name) allowing you to maintain a "YAML":http://www.yaml.org/ file of short URLs that redirect to target URLs with a set of specified Google Analytics variables. It could be used to attach any number of parameters by any name to the query string.
4
+
5
+ h2. What it does:
6
+
7
+ *example promo url*:
8
+
9
+ @http://zetetic.net/c/blog-rack-campaign@
10
+
11
+ When the user visits this link, our web server sees the /c/ location and forwards it to rack-campaign, which looks up 'blog-rack-campaign' in the YAML file, and redirects the user to the full URL, with campaign variables attached.
12
+
13
+ *resulting full url*:
14
+
15
+ @http://www.zetetic.net/blog/2010/06/11/introducing-rack-campaign?utm_campaign=rack-campaign&utm_source=blog&utm_medium=internets&utm_content=example%20link@
16
+
17
+ The former is much better than the latter, especially for newsletters and other promotional links. And with a Rack application and a YAML file you can host it yourself, you don't need to rely on bit.ly or other URL shorteners, and you can "fix" any mistakes after publishing a URL simply by updating the YAML file and reloading Unicorn (taking advantage of zero down-time!) [ _You could use another Rack-server, we like Unicorn._ ]
18
+
19
+ h2. Installation
20
+
21
+ @gem install rack-campaign@
22
+
23
+ The rest depends on how you intend to use it.
24
+
25
+ h2. Example Files
26
+
27
+ In the @/examples@ directory of the source distribution are some sample configuration files. @config.ru@ is a @rackup@ file, initializing the rack-campaign middleware. You don't have to use rack-campaign as a stand-alone Rack application, you could instead use it in a middleware stack (although you might want to modify it's behavior). You probably want to use the map directive in that case to assign rack-campaign to a particular url path (we use /c).
28
+
29
+ h2. Example Configuration
30
+
31
+ This is how we use rack-campaign as a stand-alone Rack application. Nginx is our web-server, and we use Unicorn to serve up rack-campaign for the /c path:
32
+
33
+ */www/campaigns/campaigns.yml*:
34
+
35
+ <pre><code>
36
+ blog-rack-campaign:
37
+ url: http://dev.zetetic.net/blog/2010/06/11/introducing-rack-campaign
38
+ tokens:
39
+ campaign: rack-campaign
40
+ source: blog
41
+ medium: internets
42
+ content: example link
43
+
44
+ blog-getstrip:
45
+ url: http://getstrip.com
46
+ tokens:
47
+ campaign: rack-campaign
48
+ source: blog
49
+ medium: internets
50
+ term: strip rocks!
51
+ content: example link
52
+ </code></pre>
53
+
54
+ */www/campaigns/config.ru*:
55
+
56
+ <pre><code>
57
+ # Rack-up application config
58
+
59
+ require 'rubygems'
60
+ require 'rack/zetetic/rack-campaign'
61
+
62
+ run Rack::Zetetic::CampaignLink.new('/www/campaigns/campaigns.yml')
63
+ </code></pre>
64
+
65
+ *nginx.conf*:
66
+
67
+ <pre><code>
68
+ # define upstream for campaign routing
69
+ upstream campaigns {
70
+ server unix:/www/campaigns/tmp/sockets/unicorn.sock;
71
+ }
72
+
73
+ location /c {
74
+ proxy_redirect off;
75
+ proxy_set_header Host $host;
76
+ proxy_set_header X-Real-IP $remote_addr;
77
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
78
+ proxy_max_temp_file_size 0;
79
+
80
+ # forward everything else to the mongrel cluster
81
+ if (!-f $request_filename) {
82
+ proxy_pass http://campaigns;
83
+ break;
84
+ }
85
+ }
86
+ </code></pre>
87
+
88
+ */etc/init.d/unicorn_rack*:
89
+
90
+ <pre><code>
91
+ #!/bin/bash
92
+ #
93
+ # unicorn_rack Startup script for Unicorn master processes
94
+ #
95
+ # chkconfig: - 85 15
96
+ # description: unicorn is a magical process offering up workers to nginx
97
+ #
98
+
99
+ USER=mongrel
100
+ RETVAL=0
101
+ APPS=( '/www/campaigns' )
102
+
103
+ for APP in "${APPS[@]}"
104
+ do
105
+ case "$1" in
106
+ start)
107
+ echo "Starting up $APP"
108
+ cd $APP
109
+ sudo -u $USER unicorn -c $APP/unicorn.rb -E production -D
110
+ RETVAL=$?
111
+ ;;
112
+ stop)
113
+ echo "Stopping $APP"
114
+ PID=`ps auxw | grep 'unicorn master' | grep $APP | grep -v grep | awk '{ print $2 }'`
115
+ sudo -u $USER kill -INT $PID
116
+ RETVAL=$?
117
+ ;;
118
+ restart)
119
+ $0 stop
120
+ sleep 2
121
+ $0 start
122
+ ;;
123
+ reload)
124
+ echo "Re-loading $APPS"
125
+ PID=`ps auxw | grep 'unicorn master' | grep $APP | grep -v grep | awk '{ print $2 }'`
126
+ sudo -u $USER kill -HUP $PID
127
+ RETVAL=$?
128
+ ;;
129
+ *)
130
+ echo "Usage: unicorn_rack {start|stop|restart|reload}"
131
+ exit 1
132
+ ;;
133
+ esac
134
+ done
135
+
136
+ exit $RETVAL
137
+ </code></pre>
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'date'
5
5
  require 'spec/rake/spectask'
6
6
 
7
7
  GEM = "rack-campaign"
8
- GEM_VERSION = "0.0.2"
8
+ GEM_VERSION = "0.0.3"
9
9
  AUTHOR = "Billy Gray"
10
10
  EMAIL = "wgray@zetetic.net"
11
11
  HOMEPAGE = "http://github.com/billymeltdown/rack-campaign"
@@ -25,7 +25,7 @@ spec = Gem::Specification.new do |s|
25
25
  s.homepage = HOMEPAGE
26
26
  s.add_dependency "rack"
27
27
  s.require_path = 'lib'
28
- s.files = %w(LICENSE README.textile Rakefile) + Dir.glob("{lib}/**/*")
28
+ s.files = %w(LICENSE README.textile Rakefile) + Dir.glob("{lib}/**/*") + Dir.glob("examples/**/*")
29
29
  end
30
30
 
31
31
  task :default => :spec
@@ -0,0 +1,16 @@
1
+ blog-rack-campaign:
2
+ url: http://dev.zetetic.net/blog/2010/06/11/introducing-rack-campaign
3
+ tokens:
4
+ campaign: rack-campaign
5
+ source: blog
6
+ medium: internets
7
+ content: example link
8
+
9
+ blog-getstrip:
10
+ url: http://getstrip.com
11
+ tokens:
12
+ campaign: rack-campaign
13
+ source: blog
14
+ medium: internets
15
+ term: strip rocks!
16
+ content: example link
@@ -0,0 +1,6 @@
1
+ # Rack application
2
+
3
+ require 'rubygems'
4
+ require 'rack/zetetic/rack-campaign'
5
+
6
+ run Rack::Zetetic::CampaignLink.new('/path/to/your/campaigns.yml')
@@ -0,0 +1,47 @@
1
+ #!/bin/bash
2
+ #
3
+ # unicorn_rack Startup script for Unicorn master processes
4
+ #
5
+ # chkconfig: - 85 15
6
+ # description: unicorn is a magical process offering up workers to nginx
7
+ #
8
+
9
+ USER=mongrel
10
+ RETVAL=0
11
+ APPS=( '/www/campaigns' )
12
+
13
+ for APP in "${APPS[@]}"
14
+ do
15
+ case "$1" in
16
+ start)
17
+ echo "Starting up $APP"
18
+ cd $APP
19
+ sudo -u $USER unicorn -c $APP/unicorn.rb -E production -D
20
+ RETVAL=$?
21
+ ;;
22
+ stop)
23
+ echo "Stopping $APP"
24
+ PID=`ps auxw | grep 'unicorn master' | grep $APP | grep -v grep | awk '{ print $2 }'`
25
+ sudo -u $USER kill -INT $PID
26
+ RETVAL=$?
27
+ ;;
28
+ restart)
29
+ $0 stop
30
+ sleep 2
31
+ $0 start
32
+ ;;
33
+ reload)
34
+ echo "Re-loading $APPS"
35
+ PID=`ps auxw | grep 'unicorn master' | grep $APP | grep -v grep | awk '{ print $2 }'`
36
+ sudo -u $USER kill -HUP $PID
37
+ RETVAL=$?
38
+ ;;
39
+ *)
40
+ echo "Usage: unicorn_rack {start|stop|restart|reload}"
41
+ exit 1
42
+ ;;
43
+ esac
44
+ done
45
+
46
+ exit $RETVAL
47
+
@@ -0,0 +1,69 @@
1
+ # unicorn -c /path/to/unicorn.rb -e production -D
2
+ # Unicorn-specific config
3
+ # Largely borrowed from the Github crew
4
+
5
+ app_dir = '/www/campaign_link'
6
+ worker_processes (ENV['RACK_ENV'] == 'production' ? 6 : 2)
7
+
8
+ # Restart any workers that haven't responded in 30 seconds
9
+ timeout 30
10
+
11
+ # Load the Rack app into the master before forking workers
12
+ # for super-fast worker spawn times
13
+ preload_app true
14
+
15
+ # Listen on a Unix data socket
16
+ listen 'unix:' + app_dir + '/tmp/sockets/unicorn.sock', :backlog => 2048
17
+
18
+ ##
19
+ # REE
20
+ # http://www.rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
21
+ if GC.respond_to?(:copy_on_write_friendly=)
22
+ GC.copy_on_write_friendly = true
23
+ end
24
+
25
+ before_fork do |server, worker|
26
+ ##
27
+ # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
28
+ # immediately start loading up a new version of itself (loaded with a new
29
+ # version of our app). When this new Unicorn is completely loaded
30
+ # it will begin spawning workers. The first worker spawned will check to
31
+ # see if an .oldbin pidfile exists. If so, this means we've just booted up
32
+ # a new Unicorn and need to tell the old one that it can now die. To do so
33
+ # we send it a QUIT.
34
+ #
35
+ # Using this method we get 0 downtime deploys.
36
+
37
+ old_pid = app_dir + '/tmp/pids/unicorn.pid.oldbin'
38
+ if File.exists?(old_pid) && server.pid != old_pid
39
+ begin
40
+ Process.kill("QUIT", File.read(old_pid).to_i)
41
+ rescue Errno::ENOENT, Errno::ESRCH
42
+ # someone else did our job for us
43
+ end
44
+ end
45
+ end
46
+
47
+ after_fork do |server, worker|
48
+ ##
49
+ # Unicorn master is started as root, which is fine, but let's
50
+ # drop the workers to mongrel:mongrel (or whatever you like...)
51
+ begin
52
+ uid, gid = Process.euid, Process.egid
53
+ user, group = 'mongrel', 'mongrel'
54
+ target_uid = Etc.getpwnam(user).uid
55
+ target_gid = Etc.getgrnam(group).gid
56
+ worker.tmp.chown(target_uid, target_gid)
57
+ if uid != target_uid || gid != target_gid
58
+ Process.initgroups(user, target_gid)
59
+ Process::GID.change_privilege(target_gid)
60
+ Process::UID.change_privilege(target_uid)
61
+ end
62
+ rescue => e
63
+ if ENV['RACK_ENV'] == 'development'
64
+ STDERR.puts "couldn't change user, oh well"
65
+ else
66
+ raise e
67
+ end
68
+ end
69
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 2
9
- version: 0.0.2
8
+ - 3
9
+ version: 0.0.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Billy Gray
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-10 00:00:00 -04:00
17
+ date: 2010-06-14 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -43,6 +43,10 @@ files:
43
43
  - README.textile
44
44
  - Rakefile
45
45
  - lib/rack/zetetic/campaign_link.rb
46
+ - examples/campaigns.yml
47
+ - examples/config.ru
48
+ - examples/initscript
49
+ - examples/unicorn.rb
46
50
  has_rdoc: true
47
51
  homepage: http://github.com/billymeltdown/rack-campaign
48
52
  licenses: []