rewritten 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.rdoc +93 -0
- data/Rakefile +28 -0
- data/bin/rewritten-web.rb +25 -0
- data/config.ru +4 -0
- data/lib/rack/dummy.rb +22 -0
- data/lib/rack/html.rb +44 -0
- data/lib/rack/record.rb +30 -0
- data/lib/rack/url.rb +47 -0
- data/lib/rewritten/config.ru +4 -0
- data/lib/rewritten/helpers.rb +58 -0
- data/lib/rewritten/server/public/favicon.ico +0 -0
- data/lib/rewritten/server/public/idle.png +0 -0
- data/lib/rewritten/server/public/jquery-1.3.2.min.js +19 -0
- data/lib/rewritten/server/public/jquery.relatize_date.js +95 -0
- data/lib/rewritten/server/public/poll.png +0 -0
- data/lib/rewritten/server/public/ranger.js +73 -0
- data/lib/rewritten/server/public/reset.css +48 -0
- data/lib/rewritten/server/public/style.css +85 -0
- data/lib/rewritten/server/public/working.png +0 -0
- data/lib/rewritten/server/test_helper.rb +19 -0
- data/lib/rewritten/server/views/clear_hits.erb +10 -0
- data/lib/rewritten/server/views/delete.erb +16 -0
- data/lib/rewritten/server/views/error.erb +1 -0
- data/lib/rewritten/server/views/failed.erb +64 -0
- data/lib/rewritten/server/views/hits.erb +30 -0
- data/lib/rewritten/server/views/key_sets.erb +19 -0
- data/lib/rewritten/server/views/key_string.erb +11 -0
- data/lib/rewritten/server/views/layout.erb +44 -0
- data/lib/rewritten/server/views/mappings.erb +61 -0
- data/lib/rewritten/server/views/new.erb +16 -0
- data/lib/rewritten/server/views/next_more.erb +11 -0
- data/lib/rewritten/server/views/overview.erb +8 -0
- data/lib/rewritten/server/views/queues.erb +49 -0
- data/lib/rewritten/server/views/stats.erb +62 -0
- data/lib/rewritten/server/views/to.erb +22 -0
- data/lib/rewritten/server/views/workers.erb +109 -0
- data/lib/rewritten/server/views/working.erb +72 -0
- data/lib/rewritten/server.rb +209 -0
- data/lib/rewritten/version.rb +3 -0
- data/lib/rewritten.rb +403 -0
- data/lib/test.ru +17 -0
- data/rewritten.gemspec +40 -0
- data/test/test_rewritten.rb +6 -0
- metadata +174 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
<h1 class='wi'><%= params[:to] %> (App URL)</h1>
|
3
|
+
|
4
|
+
<a href="<%= u(%|/new?to=#{params[:to]}|) %>"> + add Another translation </a>
|
5
|
+
|
6
|
+
<table class='queues'>
|
7
|
+
<tr>
|
8
|
+
<th>Translations (Browser Location Bar) </th>
|
9
|
+
<th>Action</th>
|
10
|
+
</tr>
|
11
|
+
|
12
|
+
<% for translation in Rewritten.list_range("to:#{params[:to]}", 0, 100) %>
|
13
|
+
<tr>
|
14
|
+
<td class=''><a href="<%= translation %>" target="new"><%= translation %></td>
|
15
|
+
<td class=''><a href="<%= u("/delete?from=#{translation}&to=#{params[:to]}") %>">Delete</a></td>
|
16
|
+
</tr>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
</table>
|
20
|
+
|
21
|
+
|
22
|
+
|
@@ -0,0 +1,109 @@
|
|
1
|
+
<% @subtabs = worker_hosts.keys.sort unless worker_hosts.size == 1 %>
|
2
|
+
|
3
|
+
<% if params[:id] && worker = Resque::Worker.find(params[:id]) %>
|
4
|
+
|
5
|
+
<h1>Worker <%= worker %></h1>
|
6
|
+
<table class='workers'>
|
7
|
+
<tr>
|
8
|
+
<th> </th>
|
9
|
+
<th>Host</th>
|
10
|
+
<th>Pid</th>
|
11
|
+
<th>Started</th>
|
12
|
+
<th>Queues</th>
|
13
|
+
<th>Processed</th>
|
14
|
+
<th>Failed</th>
|
15
|
+
<th>Processing</th>
|
16
|
+
</tr>
|
17
|
+
<tr>
|
18
|
+
<td class='icon'><img src="<%=u state = worker.state %>.png" alt="<%= state %>" title="<%= state %>"></td>
|
19
|
+
|
20
|
+
<% host, pid, queues = worker.to_s.split(':') %>
|
21
|
+
<td><%= host %></td>
|
22
|
+
<td><%= pid %></td>
|
23
|
+
<td><span class="time"><%= worker.started %></span></td>
|
24
|
+
<td class='queues'><%= queues.split(',').map { |q| '<a class="queue-tag" href="' + u("/queues/#{q}") + '">' + q + '</a>'}.join('') %></td>
|
25
|
+
<td><%= worker.processed %></td>
|
26
|
+
<td><%= worker.failed %></td>
|
27
|
+
<td class='process'>
|
28
|
+
<% data = worker.processing || {} %>
|
29
|
+
<% if data['queue'] %>
|
30
|
+
<code><%= data['payload']['class'] %></code>
|
31
|
+
<small><a class="queue time" href="<%=u "/working/#{worker}" %>"><%= data['run_at'] %></a></small>
|
32
|
+
<% else %>
|
33
|
+
<span class='waiting'>Waiting for a job...</span>
|
34
|
+
<% end %>
|
35
|
+
</td>
|
36
|
+
</tr>
|
37
|
+
</table>
|
38
|
+
|
39
|
+
<% elsif params[:id] && !worker_hosts.keys.include?(params[:id]) && params[:id] != 'all' %>
|
40
|
+
|
41
|
+
<h1>Worker doesn't exist</h1>
|
42
|
+
|
43
|
+
<% elsif worker_hosts.size == 1 || params[:id] %>
|
44
|
+
|
45
|
+
<% if worker_hosts.size == 1 || params[:id] == 'all' %>
|
46
|
+
<% workers = Resque.workers %>
|
47
|
+
<% else %>
|
48
|
+
<% workers = worker_hosts[params[:id]].map { |id| Resque::Worker.find(id) } %>
|
49
|
+
<% end %>
|
50
|
+
|
51
|
+
<h1 class='wi'><%= workers.size %> Workers</h1>
|
52
|
+
<p class='intro'>The workers listed below are all registered as active on your system.</p>
|
53
|
+
<table class='workers'>
|
54
|
+
<tr>
|
55
|
+
<th> </th>
|
56
|
+
<th>Where</th>
|
57
|
+
<th>Queues</th>
|
58
|
+
<th>Processing</th>
|
59
|
+
</tr>
|
60
|
+
<% for worker in (workers = workers.sort_by { |w| w.to_s }) %>
|
61
|
+
<tr class="<%=state = worker.state%>">
|
62
|
+
<td class='icon'><img src="<%=u state %>.png" alt="<%= state %>" title="<%= state %>"></td>
|
63
|
+
|
64
|
+
<% host, pid, queues = worker.to_s.split(':') %>
|
65
|
+
<td class='where'><a href="<%=u "workers/#{worker}"%>"><%= host %>:<%= pid %></a></td>
|
66
|
+
<td class='queues'><%= queues.split(',').map { |q| '<a class="queue-tag" href="' + u("/queues/#{q}") + '">' + q + '</a>'}.join('') %></td>
|
67
|
+
|
68
|
+
<td class='process'>
|
69
|
+
<% data = worker.processing || {} %>
|
70
|
+
<% if data['queue'] %>
|
71
|
+
<code><%= data['payload']['class'] %></code>
|
72
|
+
<small><a class="queue time" href="<%=u "/working/#{worker}" %>"><%= data['run_at'] %></a></small>
|
73
|
+
<% else %>
|
74
|
+
<span class='waiting'>Waiting for a job...</span>
|
75
|
+
<% end %>
|
76
|
+
</td>
|
77
|
+
</tr>
|
78
|
+
<% end %>
|
79
|
+
<% if workers.empty? %>
|
80
|
+
<tr>
|
81
|
+
<td colspan='4' class='no-data'>There are no registered workers</td>
|
82
|
+
</tr>
|
83
|
+
<% end %>
|
84
|
+
</table>
|
85
|
+
<%=poll%>
|
86
|
+
|
87
|
+
<% else %>
|
88
|
+
<% @subtabs = [] %>
|
89
|
+
<h1 class='wi'>Workers</h1>
|
90
|
+
<p class='intro'>The hostnames below all have registered workers. Select a hostname to view its workers, or "all" to see all workers.</p>
|
91
|
+
<table class='queues'>
|
92
|
+
<tr>
|
93
|
+
<th>Hostname</th>
|
94
|
+
<th>Workers</th>
|
95
|
+
</tr>
|
96
|
+
<% for hostname, workers in worker_hosts.sort_by { |h,w| h } %>
|
97
|
+
<tr>
|
98
|
+
<td class='queue'><a class="queue" href="<%= u "workers/#{hostname}" %>"><%= hostname %></a></td>
|
99
|
+
<td class='size'><%= workers.size %></td>
|
100
|
+
</tr>
|
101
|
+
<% end %>
|
102
|
+
<tr class="failed">
|
103
|
+
<td class='queue failed'><a class="queue" href="<%= u "workers/all" %>">all workers</a></td>
|
104
|
+
<td class='size'><%= Resque.workers.size %></td>
|
105
|
+
</tr>
|
106
|
+
</table>
|
107
|
+
|
108
|
+
|
109
|
+
<% end %>
|
@@ -0,0 +1,72 @@
|
|
1
|
+
<% if params[:id] && (worker = Resque::Worker.find(params[:id])) && worker.job %>
|
2
|
+
<h1><%= worker %>'s job</h1>
|
3
|
+
|
4
|
+
<table>
|
5
|
+
<tr>
|
6
|
+
<th> </th>
|
7
|
+
<th>Where</th>
|
8
|
+
<th>Queue</th>
|
9
|
+
<th>Started</th>
|
10
|
+
<th>Class</th>
|
11
|
+
<th>Args</th>
|
12
|
+
</tr>
|
13
|
+
<tr>
|
14
|
+
<td><img src="<%=u 'working.png' %>" alt="working" title="working"></td>
|
15
|
+
<% host, pid, _ = worker.to_s.split(':') %>
|
16
|
+
<td><a href="<%=u "/workers/#{worker}" %>"><%= host %>:<%= pid %></a></td>
|
17
|
+
<% data = worker.job %>
|
18
|
+
<% queue = data['queue'] %>
|
19
|
+
<td><a class="queue" href="<%=u "/queues/#{queue}" %>"><%= queue %></a></td>
|
20
|
+
<td><span class="time"><%= data['run_at'] %></span></td>
|
21
|
+
<td>
|
22
|
+
<code><%= data['payload']['class'] %></code>
|
23
|
+
</td>
|
24
|
+
<td><%=h data['payload']['args'].inspect %></td>
|
25
|
+
</tr>
|
26
|
+
</table>
|
27
|
+
|
28
|
+
<% else %>
|
29
|
+
|
30
|
+
<%
|
31
|
+
workers = resque.working
|
32
|
+
jobs = workers.collect {|w| w.job }
|
33
|
+
worker_jobs = workers.zip(jobs)
|
34
|
+
worker_jobs = worker_jobs.reject { |w, j| w.idle? }
|
35
|
+
%>
|
36
|
+
|
37
|
+
<h1 class='wi'><%= worker_jobs.size %> of <%= resque.workers.size %> Workers Working</h1>
|
38
|
+
<p class='intro'>The list below contains all workers which are currently running a job.</p>
|
39
|
+
<table class='workers'>
|
40
|
+
<tr>
|
41
|
+
<th> </th>
|
42
|
+
<th>Where</th>
|
43
|
+
<th>Queue</th>
|
44
|
+
<th>Processing</th>
|
45
|
+
</tr>
|
46
|
+
<% if worker_jobs.empty? %>
|
47
|
+
<tr>
|
48
|
+
<td colspan="4" class='no-data'>Nothing is happening right now...</td>
|
49
|
+
</tr>
|
50
|
+
<% end %>
|
51
|
+
|
52
|
+
<% worker_jobs.sort_by {|w, j| j['run_at'] ? j['run_at'] : '' }.each do |worker, job| %>
|
53
|
+
<tr>
|
54
|
+
<td class='icon'><img src="<%=u state = worker.state %>.png" alt="<%= state %>" title="<%= state %>"></td>
|
55
|
+
<% host, pid, queues = worker.to_s.split(':') %>
|
56
|
+
<td class='where'><a href="<%=u "/workers/#{worker}" %>"><%= host %>:<%= pid %></a></td>
|
57
|
+
<td class='queues queue'>
|
58
|
+
<a class="queue-tag" href="<%=u "/queues/#{job['queue']}" %>"><%= job['queue'] %></a>
|
59
|
+
</td>
|
60
|
+
<td class='process'>
|
61
|
+
<% if job['queue'] %>
|
62
|
+
<code><%= job['payload']['class'] %></code>
|
63
|
+
<small><a class="queue time" href="<%=u "/working/#{worker}" %>"><%= job['run_at'] %></a></small>
|
64
|
+
<% else %>
|
65
|
+
<span class='waiting'>Waiting for a job...</span>
|
66
|
+
<% end %>
|
67
|
+
</td>
|
68
|
+
</tr>
|
69
|
+
<% end %>
|
70
|
+
</table>
|
71
|
+
|
72
|
+
<% end %>
|
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'erb'
|
3
|
+
require 'rewritten'
|
4
|
+
require 'rewritten/version'
|
5
|
+
require 'time'
|
6
|
+
|
7
|
+
module Rewritten
|
8
|
+
class Server < Sinatra::Base
|
9
|
+
|
10
|
+
dir = File.dirname(File.expand_path(__FILE__))
|
11
|
+
|
12
|
+
set :views, "#{dir}/server/views"
|
13
|
+
set :public, "#{dir}/server/public"
|
14
|
+
set :static, true
|
15
|
+
|
16
|
+
helpers do
|
17
|
+
include Rack::Utils
|
18
|
+
alias_method :h, :escape_html
|
19
|
+
|
20
|
+
def current_section
|
21
|
+
url_path request.path_info.sub('/','').split('/')[0].downcase
|
22
|
+
end
|
23
|
+
|
24
|
+
def current_page
|
25
|
+
url_path request.path_info.sub('/','')
|
26
|
+
end
|
27
|
+
|
28
|
+
def url_path(*path_parts)
|
29
|
+
[ path_prefix, path_parts ].join("/").squeeze('/')
|
30
|
+
end
|
31
|
+
alias_method :u, :url_path
|
32
|
+
|
33
|
+
def path_prefix
|
34
|
+
request.env['SCRIPT_NAME']
|
35
|
+
end
|
36
|
+
|
37
|
+
def class_if_current(path = '')
|
38
|
+
'class="current"' if current_page[0, path.size] == path
|
39
|
+
end
|
40
|
+
|
41
|
+
def tab(name)
|
42
|
+
dname = name.to_s.downcase
|
43
|
+
path = url_path(dname)
|
44
|
+
"<li #{class_if_current(path)}><a href='#{path}'>#{name}</a></li>"
|
45
|
+
end
|
46
|
+
|
47
|
+
def tabs
|
48
|
+
Rewritten::Server.tabs
|
49
|
+
end
|
50
|
+
|
51
|
+
def redis_get_size(key)
|
52
|
+
case Resque.redis.type(key)
|
53
|
+
when 'none'
|
54
|
+
[]
|
55
|
+
when 'list'
|
56
|
+
Resque.redis.llen(key)
|
57
|
+
when 'set'
|
58
|
+
Resque.redis.scard(key)
|
59
|
+
when 'string'
|
60
|
+
Resque.redis.get(key).length
|
61
|
+
when 'zset'
|
62
|
+
Resque.redis.zcard(key)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def redis_get_value_as_array(key, start=0)
|
67
|
+
case Resque.redis.type(key)
|
68
|
+
when 'none'
|
69
|
+
[]
|
70
|
+
when 'list'
|
71
|
+
Resque.redis.lrange(key, start, start + 20)
|
72
|
+
when 'set'
|
73
|
+
Resque.redis.smembers(key)[start..(start + 20)]
|
74
|
+
when 'string'
|
75
|
+
[Resque.redis.get(key)]
|
76
|
+
when 'zset'
|
77
|
+
Resque.redis.zrange(key, start, start + 20)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def show_args(args)
|
82
|
+
Array(args).map { |a| a.inspect }.join("\n")
|
83
|
+
end
|
84
|
+
|
85
|
+
def worker_hosts
|
86
|
+
@worker_hosts ||= worker_hosts!
|
87
|
+
end
|
88
|
+
|
89
|
+
def worker_hosts!
|
90
|
+
hosts = Hash.new { [] }
|
91
|
+
|
92
|
+
Resque.workers.each do |worker|
|
93
|
+
host, _ = worker.to_s.split(':')
|
94
|
+
hosts[host] += [worker.to_s]
|
95
|
+
end
|
96
|
+
|
97
|
+
hosts
|
98
|
+
end
|
99
|
+
|
100
|
+
def partial?
|
101
|
+
@partial
|
102
|
+
end
|
103
|
+
|
104
|
+
def partial(template, local_vars = {})
|
105
|
+
@partial = true
|
106
|
+
erb(template.to_sym, {:layout => false}, local_vars)
|
107
|
+
ensure
|
108
|
+
@partial = false
|
109
|
+
end
|
110
|
+
|
111
|
+
def poll
|
112
|
+
if @polling
|
113
|
+
text = "Last Updated: #{Time.now.strftime("%H:%M:%S")}"
|
114
|
+
else
|
115
|
+
text = "<a href='#{u(request.path_info)}.poll' rel='poll'>Live Poll</a>"
|
116
|
+
end
|
117
|
+
"<p class='poll'>#{text}</p>"
|
118
|
+
end
|
119
|
+
|
120
|
+
end # enf of helpers
|
121
|
+
|
122
|
+
|
123
|
+
def show(page, layout = true)
|
124
|
+
begin
|
125
|
+
erb page.to_sym, {:layout => layout}, :rewritten => Rewritten
|
126
|
+
rescue Errno::ECONNREFUSED
|
127
|
+
erb :error, {:layout => false}, :error => "Can't connect to Redis! (#{Rewritten.redis_id})"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def show_for_polling(page)
|
132
|
+
content_type "text/html"
|
133
|
+
@polling = true
|
134
|
+
show(page.to_sym, false).gsub(/\s{1,}/, ' ')
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
################################################################################
|
139
|
+
|
140
|
+
|
141
|
+
get "/?" do
|
142
|
+
redirect url_path(:overview)
|
143
|
+
end
|
144
|
+
|
145
|
+
get "/overview" do
|
146
|
+
show 'overview'
|
147
|
+
end
|
148
|
+
|
149
|
+
get "/new" do
|
150
|
+
show "new"
|
151
|
+
end
|
152
|
+
|
153
|
+
post "/mappings" do
|
154
|
+
if params[:from]!='' && params[:to]!=''
|
155
|
+
Rewritten.add_translation(params[:from], params[:to])
|
156
|
+
redirect u('overview')
|
157
|
+
else
|
158
|
+
show "new"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
get "/to" do
|
163
|
+
translations = Rewritten.list_range(params[:to], 0, -1)
|
164
|
+
show "to"
|
165
|
+
end
|
166
|
+
|
167
|
+
get "/delete" do
|
168
|
+
@from = params[:from]
|
169
|
+
@to = params[:to]
|
170
|
+
show "delete"
|
171
|
+
end
|
172
|
+
|
173
|
+
post '/delete' do
|
174
|
+
|
175
|
+
from = params[:from]
|
176
|
+
to = params[:to]
|
177
|
+
|
178
|
+
Rewritten.remove_translation(from, to)
|
179
|
+
|
180
|
+
if Rewritten.num_translations(to) > 0
|
181
|
+
redirect u("/to?to=#{to}")
|
182
|
+
else
|
183
|
+
redirect u("/")
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
get "/hits" do
|
189
|
+
show "hits"
|
190
|
+
end
|
191
|
+
|
192
|
+
get "/hits/clear" do
|
193
|
+
show "clear_hits"
|
194
|
+
end
|
195
|
+
|
196
|
+
post "/hits/clear" do
|
197
|
+
Rewritten.redis.del("hits")
|
198
|
+
redirect u("/hits")
|
199
|
+
end
|
200
|
+
|
201
|
+
def self.tabs
|
202
|
+
#@tabs ||= ["Overview", "Working", "Failed", "Queues", "Workers", "Stats"]
|
203
|
+
@tabs ||= ["Overview", "Hits"]
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
|