Module: Rewritten

Extended by:
Rewritten
Includes:
Helpers
Included in:
Rewritten
Defined in:
lib/rewritten.rb,
lib/rewritten/server.rb,
lib/rewritten/helpers.rb,
lib/rewritten/version.rb,
lib/rewritten/document.rb,
lib/rewritten/rails/url_helpers.rb

Defined Under Namespace

Modules: Document, Helpers, Rails Classes: Server

Constant Summary collapse

VERSION =
"0.15.0"

Instance Method Summary collapse

Methods included from Helpers

#classify, #constantize, #decode, #encode

Instance Method Details

#add_hit(path, code, content_type) ⇒ Object



294
295
296
297
# File 'lib/rewritten.rb', line 294

def add_hit(path, code, content_type)
  h = {:path => path, :code => code, :content_type => content_type}
  Rewritten.redis.sadd("hits", encode(h) )
end

#add_translation(line, to) ⇒ Object

translations



138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/rewritten.rb', line 138

def add_translation(line, to)
  from, flags = line.split(/\s+/)

  flags = flags.scan(/\[(\w+)\]/).first if flags

  redis.hset("from:#{from}", :to, to)
  redis.hset("from:#{from}", :flags, flags) if flags

  redis.sadd(:froms, from) 
  redis.sadd(:tos, to) 
  score = redis.zcard("to:#{to}") || 0
  redis.zadd("to:#{to}", score, from)  
end

#add_translations(to, froms) ⇒ Object



152
153
154
# File 'lib/rewritten.rb', line 152

def add_translations(to, froms)
  froms.each {|from|  add_translation(from, to)}
end

#after_fork(&block) ⇒ Object

The after_fork hook will be run in the child process and is passed the current job. Any changes you make, therefore, will only live as long as the job currently being processed.

Call with a block to set the hook. Call with no arguments to return the hook.



109
110
111
# File 'lib/rewritten.rb', line 109

def after_fork(&block)
  block ? (@after_fork = block) : @after_fork
end

#after_fork=(after_fork) ⇒ Object

Set the after_fork proc.



114
115
116
# File 'lib/rewritten.rb', line 114

def after_fork=(after_fork)
  @after_fork = after_fork
end

#all_fromsObject



182
183
184
# File 'lib/rewritten.rb', line 182

def all_froms
  Array(redis.smembers(:froms))
end

#all_hitsObject



299
300
301
# File 'lib/rewritten.rb', line 299

def all_hits
  Rewritten.redis.smembers("hits").map{|e| decode(e)}
end

#all_tosObject



186
187
188
# File 'lib/rewritten.rb', line 186

def all_tos
  Array(Rewritten.redis.smembers(:tos))
end

#appendix(some_from) ⇒ Object



264
265
266
267
268
# File 'lib/rewritten.rb', line 264

def appendix(some_from)
  base = base_from(some_from) || ''
  result = some_from.partition( base ).last
  result.chomp('/')
end

#base_from(some_from) ⇒ Object



250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/rewritten.rb', line 250

def base_from(some_from)
  base_from = some_from.split('?')[0].chomp('/')
  if translate(some_from)
    some_from
  elsif translate(base_from)
    base_from
  elsif translate_partial? && base_from.count('/') > 1
    parts = base_from.split('/')
    base_from(parts.slice(0,parts.size-1).join('/'))
  else
    nil
  end
end

#before_first_fork(&block) ⇒ Object

The before_first_fork hook will be run in the parent process only once, before forking to run the first job. Be careful- any changes you make will be permanent for the lifespan of the worker.

Call with a block to set the hook. Call with no arguments to return the hook.



78
79
80
# File 'lib/rewritten.rb', line 78

def before_first_fork(&block)
  block ? (@before_first_fork = block) : @before_first_fork
end

#before_first_fork=(before_first_fork) ⇒ Object

Set a proc that will be called in the parent process before the worker forks for the first time.



84
85
86
# File 'lib/rewritten.rb', line 84

def before_first_fork=(before_first_fork)
  @before_first_fork = before_first_fork
end

#before_fork(&block) ⇒ Object

The before_fork hook will be run in the parent process before every job, so be careful- any changes you make will be permanent for the lifespan of the worker.

Call with a block to set the hook. Call with no arguments to return the hook.



94
95
96
# File 'lib/rewritten.rb', line 94

def before_fork(&block)
  block ? (@before_fork = block) : @before_fork
end

#before_fork=(before_fork) ⇒ Object

Set the before_fork proc.



99
100
101
# File 'lib/rewritten.rb', line 99

def before_fork=(before_fork)
  @before_fork = before_fork
end

#clear_translationsObject



173
174
175
# File 'lib/rewritten.rb', line 173

def clear_translations
  Rewritten.redis.del(*Rewritten.redis.keys) unless Rewritten.redis.keys.empty?
end

#exist_translation_for?(path) ⇒ Boolean

Returns:

  • (Boolean)


290
291
292
# File 'lib/rewritten.rb', line 290

def exist_translation_for?(path)
  get_current_translation(path) != path
end

#fromsObject

Returns an array of all known source URLs (that are to translated)



178
179
180
# File 'lib/rewritten.rb', line 178

def froms
  Array(redis.smembers(:froms))
end

#full_line(from) ⇒ Object



279
280
281
282
283
284
285
286
287
288
# File 'lib/rewritten.rb', line 279

def full_line(from)
  flags = get_flag_string(from)

  if flags == ""
    from
  else
    "#{from} [#{flags}]" 
  end

end

#get_all_translations(to) ⇒ Object



194
195
196
# File 'lib/rewritten.rb', line 194

def get_all_translations(to)
  Rewritten.redis.zrange("to:#{to}", 0, -1)
end

#get_current_translation(path, tail = nil) ⇒ Object



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/rewritten.rb', line 198

def get_current_translation(path, tail=nil)

  uri = URI.parse(path)

  # find directly
  translation = Rewritten.z_range("to:#{path}", -1)
 
  unless translation 
    translation = Rewritten.z_range("to:#{uri.path}", -1)
  end

  if translation.nil?
    if translate_partial? && path.count('/') > 1
      parts = path.split('/')
      shorter_path = parts.slice(0, parts.size-1).join('/')
      appendix = parts.last + (tail ? "/" + tail : "")
      return get_current_translation(shorter_path, appendix) 
    else
      return path
    end
  end

  complete_path = (tail ? translation+"/"+tail : translation)
  translated_uri = URI.parse(complete_path)
  uri.path = translated_uri.path
  uri.query = [translated_uri.query, uri.query].compact.join('&')
  uri.query = nil if uri.query == ''
  uri.to_s
end

#get_flag_string(from) ⇒ Object



270
271
272
# File 'lib/rewritten.rb', line 270

def get_flag_string(from)
  Rewritten.redis.hget("from:#{from}", :flags)||""
end

#has_flag?(from, c) ⇒ Boolean

Returns:

  • (Boolean)


274
275
276
277
# File 'lib/rewritten.rb', line 274

def has_flag?(from, c)
  return false unless Rewritten.redis.exists("from:#{from}")
  get_flag_string(from).index(c) != nil
end

#includes?(path) ⇒ Boolean

Returns:

  • (Boolean)


303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'lib/rewritten.rb', line 303

def includes?(path)

  result = Rewritten.redis.hget("from:#{path.chomp('/')}", :to)
  result = Rewritten.redis.hget("from:#{path.split('?')[0]}", :to) unless result

  if result.nil? && translate_partial? && path.count('/') > 1
    parts = path.split('/')
    includes?( parts.slice(0,parts.size-1).join('/') )
  else
    result
  end

end

#infinitive(some_from) ⇒ Object

infinitive for translations only!



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/rewritten.rb', line 230

def infinitive(some_from)

  some_from ||= ''

  conjugated = some_from.chomp('/')

  to = translate(conjugated)
  to = translate(conjugated.split('?')[0]) unless to

  if to.nil? && translate_partial? && conjugated.count('/') > 1 
    parts = conjugated.split('/')
    shorter_path = parts.slice(0, parts.size-1).join('/')
    infinitive(shorter_path)
  else
    conjugated = get_current_translation(to) if to
    conjugated = conjugated.split('?')[0] || ''
    conjugated.chomp('/')
  end
end

#infoObject

Returns a hash, similar to redis-rb’s #info, of interesting stats.



362
363
364
365
366
367
368
369
370
371
372
373
# File 'lib/rewritten.rb', line 362

def info
  return {
    :pending   => queues.inject(0) { |m,k| m + size(k) },
    #:processed => Stat[:processed],
    #:queues    => queues.size,
    #:workers   => workers.size.to_i,
    #:working   => working.size,
    #:failed    => Stat[:failed],
    :servers   => [redis_id],
    :environment  => ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
  }
end

#inline=(inline) ⇒ Object



130
131
132
# File 'lib/rewritten.rb', line 130

def inline=(inline)
  @inline = inline
end

#inline?Boolean Also known as: inline

If ‘inline’ is true Resque will call #perform method inline without queuing it into Redis and without any Resque callbacks. The ‘inline’ is false Resque jobs will be put in queue regularly.

Returns:

  • (Boolean)


125
126
127
# File 'lib/rewritten.rb', line 125

def inline?
  @inline
end

#keysObject

Returns an array of all known Resque keys in Redis. Redis’ KEYS operation is O(N) for the keyspace, so be careful - this can be slow for big databases.



377
378
379
380
381
# File 'lib/rewritten.rb', line 377

def keys
  redis.keys("*").map do |key|
    key.sub("#{redis.namespace}:", '')
  end
end

#num_fromsObject

return the number of froms



318
319
320
# File 'lib/rewritten.rb', line 318

def num_froms
  redis.scard(:froms).to_i
end

#num_translations(to) ⇒ Object



156
157
158
# File 'lib/rewritten.rb', line 156

def num_translations(to)
  Rewritten.redis.zcard("to:#{to}")
end

#per_pageObject



383
384
385
# File 'lib/rewritten.rb', line 383

def per_page
  20
end

#queuesObject

Returns an array of all known Resque queues as strings.



335
336
337
# File 'lib/rewritten.rb', line 335

def queues
  Array(redis.smembers(:queues))
end

#redisObject

Returns the current Redis connection. If none has been created, will create a new one.



54
55
56
57
58
# File 'lib/rewritten.rb', line 54

def redis
  return @redis if @redis
  self.redis = Redis.respond_to?(:connect) ? Redis.connect : "localhost:6379"
  self.redis
end

#redis=(server) ⇒ Object

Accepts:

1. A 'hostname:port' String
2. A 'hostname:port:db' String (to select the Redis db)
3. A 'hostname:port/namespace' String (to set the Redis namespace)
4. A Redis URL String 'redis://host:port'
5. An instance of `Redis`, `Redis::Client`, `Redis::DistRedis`,
   or `Redis::Namespace`.


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/rewritten.rb', line 23

def redis=(server)
  case server
  when String
    if server =~ /redis\:\/\//
      redis = Redis.connect(:url => server, :thread_safe => true)
    else
      server, namespace = server.split('/', 2)
      host, port, db = server.split(':')
      redis = Redis.new(:host => host, :port => port,
        :thread_safe => true, :db => db)
    end
    namespace ||= :rewritten

    @redis = Redis::Namespace.new(namespace, :redis => redis)
  when Redis::Namespace
    @redis = server
  else
    @redis = Redis::Namespace.new(:rewritten, :redis => server)
  end
end

#redis_idObject



60
61
62
63
64
65
66
67
68
69
# File 'lib/rewritten.rb', line 60

def redis_id
  # support 1.x versions of redis-rb
  if redis.respond_to?(:server)
    redis.server
  elsif redis.respond_to?(:nodes) # distributed
    redis.nodes.map { |n| n.id }.join(', ')
  else
    redis.client.id
  end
end

#remove_all_translations(to) ⇒ Object



167
168
169
170
171
# File 'lib/rewritten.rb', line 167

def remove_all_translations(to)
  get_all_translations(to).each do |from|
    Rewritten.remove_translation(from, to)
  end
end

#remove_queue(queue) ⇒ Object

Given a queue name, completely deletes the queue.



345
346
347
348
# File 'lib/rewritten.rb', line 345

def remove_queue(queue)
  redis.srem(:queues, queue.to_s)
  redis.del("queue:#{queue}")
end

#remove_translation(from, to) ⇒ Object



160
161
162
163
164
165
# File 'lib/rewritten.rb', line 160

def remove_translation(from, to)
   Rewritten.redis.del("from:#{from}")
   Rewritten.redis.srem(:froms, from)
   Rewritten.redis.zrem("to:#{to}", from)
   Rewritten.redis.srem(:tos, to) if num_translations(to) == 0
end

#targetsObject

Returns an array of all known URL targets.



340
341
342
# File 'lib/rewritten.rb', line 340

def targets 
  Array(redis.smembers(:targets))
end

#to_sObject



118
119
120
# File 'lib/rewritten.rb', line 118

def to_s
  "Rewritten Client connected to #{redis_id}"
end

#translate(from) ⇒ Object



190
191
192
# File 'lib/rewritten.rb', line 190

def translate(from)
  redis.hget("from:#{from}", :to)
end

#translate_partial=(yes_or_no) ⇒ Object



44
45
46
# File 'lib/rewritten.rb', line 44

def translate_partial=(yes_or_no)
  @translate_partial = yes_or_no
end

#translate_partial?Boolean

Returns:

  • (Boolean)


48
49
50
# File 'lib/rewritten.rb', line 48

def translate_partial?
  @translate_partial
end

#watch_queue(queue) ⇒ Object

Used internally to keep track of which queues we’ve created. Don’t call this directly.



352
353
354
# File 'lib/rewritten.rb', line 352

def watch_queue(queue)
  redis.sadd(:queues, queue.to_s)
end

#z_range(key, start = 0, count = 1) ⇒ Object

Does the dirty work of fetching a range of items from a Redis list and converting them into Ruby objects.



324
325
326
327
328
329
330
331
332
# File 'lib/rewritten.rb', line 324

def z_range(key, start = 0, count = 1)
  if count == 1
    redis.zrange(key, start, start)[0]
  else
    Array(redis.zrange(key, start, start+count-1)).map do |item|
      item
    end
  end
end