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.16.0'

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helpers

#classify, #constantize, #decode, #encode

Instance Attribute Details

#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.



103
104
105
# File 'lib/rewritten.rb', line 103

def after_fork(&block)
  block ? (@after_fork = block) : @after_fork
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.



76
77
78
# File 'lib/rewritten.rb', line 76

def before_first_fork(&block)
  block ? (@before_first_fork = block) : @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.



90
91
92
# File 'lib/rewritten.rb', line 90

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

#inline=(value) ⇒ Object

Sets the attribute inline

Parameters:

  • value

    the value to set the attribute inline to.



122
123
124
# File 'lib/rewritten.rb', line 122

def inline=(value)
  @inline = value
end

#translate_partial=(value) ⇒ Object (writeonly)

Sets the attribute translate_partial

Parameters:

  • value

    the value to set the attribute translate_partial to.



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

def translate_partial=(value)
  @translate_partial = value
end

Instance Method Details

#add_hit(path, code, content_type) ⇒ Object



276
277
278
279
# File 'lib/rewritten.rb', line 276

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



128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/rewritten.rb', line 128

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



142
143
144
# File 'lib/rewritten.rb', line 142

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

#all_fromsObject



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

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

#all_hitsObject



281
282
283
# File 'lib/rewritten.rb', line 281

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

#all_tosObject



176
177
178
# File 'lib/rewritten.rb', line 176

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

#appendix(some_from) ⇒ Object



247
248
249
250
251
# File 'lib/rewritten.rb', line 247

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

#base_from(some_from) ⇒ Object



235
236
237
238
239
240
241
242
243
244
245
# File 'lib/rewritten.rb', line 235

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('/'))
      end
end

#clear_translationsObject



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

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

#exist_translation_for?(path) ⇒ Boolean

Returns:

  • (Boolean)


272
273
274
# File 'lib/rewritten.rb', line 272

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

#flag?(from, c) ⇒ Boolean

Returns:

  • (Boolean)


257
258
259
260
# File 'lib/rewritten.rb', line 257

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

#fromsObject

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



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

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

#full_line(from) ⇒ Object



262
263
264
265
266
267
268
269
270
# File 'lib/rewritten.rb', line 262

def full_line(from)
  flags = get_flag_string(from)

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

#get_all_translations(to) ⇒ Object



184
185
186
# File 'lib/rewritten.rb', line 184

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

#get_current_translation(path, tail = nil) ⇒ Object



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/rewritten.rb', line 188

def get_current_translation(path, tail = nil)
  uri = URI.parse(path)

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

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

  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



253
254
255
# File 'lib/rewritten.rb', line 253

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

#includes?(path) ⇒ Boolean

Returns:

  • (Boolean)


285
286
287
288
289
290
291
292
293
294
295
# File 'lib/rewritten.rb', line 285

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!



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/rewritten.rb', line 216

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.



341
342
343
344
345
346
347
348
349
350
351
352
# File 'lib/rewritten.rb', line 341

def info
  {
    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?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)


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

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.



356
357
358
359
360
# File 'lib/rewritten.rb', line 356

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

#num_fromsObject

return the number of froms



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

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

#num_translations(to) ⇒ Object



146
147
148
# File 'lib/rewritten.rb', line 146

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

#per_pageObject



362
363
364
# File 'lib/rewritten.rb', line 362

def per_page
  20
end

#queuesObject

Returns an array of all known Resque queues as strings.



315
316
317
# File 'lib/rewritten.rb', line 315

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

#redisObject

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



52
53
54
55
56
# File 'lib/rewritten.rb', line 52

def redis
  return @redis if @redis
  self.redis = Redis.respond_to?(:connect) ? Redis.connect : 'localhost:6379'
  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



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

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(&:id).join(', ')
  else
    redis.client.id
  end
end

#remove_all_translations(to) ⇒ Object



157
158
159
160
161
# File 'lib/rewritten.rb', line 157

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.



325
326
327
328
# File 'lib/rewritten.rb', line 325

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

#remove_translation(from, to) ⇒ Object



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

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.



320
321
322
# File 'lib/rewritten.rb', line 320

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

#to_sObject



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

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

#translate(from) ⇒ Object



180
181
182
# File 'lib/rewritten.rb', line 180

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

#translate_partial?Boolean

Returns:

  • (Boolean)


46
47
48
# File 'lib/rewritten.rb', line 46

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.



332
333
334
# File 'lib/rewritten.rb', line 332

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.



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

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