Module | RSCM::RevisionPoller |
In: |
lib/rscm/revision_poller.rb
|
CRITICAL_REVISION_SIZE | = | 100 | This is the number of revisions we‘ll try to stick to for each call to revisions. | |
BASE_INCREMENT | = | 60*60 | ||
TWENTY_FOUR_HOURS | = | 24*60*60 |
logger | [RW] |
Polls revisions from point and either backwards in time until the beginning of time (Time.epoch) or forward in time until we‘re past now.
Whether to poll forwards or backwards in time depends on the value of direction.
The point argument can be either a Revision, String, Time or Fixnum representing where to start from (upper boundary for backwards polling, lower boundary for forwards polling).
The polling starts with a small interval from point (1 hour) and increments (or decrements) gradually in order to try and keep the length of the yielded Revisions to about 100.
The passed block will be called several times, each time with a Revisions object. In order to reduce the memory footprint and keep the performance decent, the length of each yielded Revisions object will usually be within the order of magnitude of 100.
TODO: handle non-transactional SCMs. There was some handling of this in older revisions of this file. We should dig it out and reenable it.
# File lib/rscm/revision_poller.rb, line 29 29: def poll(point=nil, direction=:backwards, multiplier=1, now=Time.now.utc, options={}, &proc) 30: raise "A block of arity 1 must be called" if proc.nil? 31: backwards = direction == :backwards 32: point ||= now 33: 34: if point.respond_to?(:time) 35: point_time = backwards ? point.time(:min) : point.time(:max) 36: point_identifier = backwards ? point.identifier(:min) : point.identifier(:max) 37: elsif point.is_a?(Time) 38: point_time = point 39: point_identifier = point 40: else 41: point_time = now 42: point_identifier = point 43: end 44: 45: increment = multiplier * BASE_INCREMENT 46: if backwards 47: to = point_identifier 48: begin 49: from = point_time - increment 50: rescue ArgumentError 51: from = Time.epoch 52: end 53: from = Time.epoch if from < Time.epoch 54: else 55: from = point_identifier 56: begin 57: to = point_time + increment 58: rescue RangeError 59: raise "RSCM will not work this far in the future (#{from} plus #{increment})" 60: end 61: end 62: 63: options = options.merge({:to_identifier => to}) 64: 65: revs = revisions(from, options) 66: raise "Got nil revision for from=#{from.inspect}" if revs.nil? 67: revs.sort! 68: proc.call(revs) 69: 70: if from == Time.epoch 71: return 72: end 73: if !backwards and to.is_a?(Time) and (to) > now + TWENTY_FOUR_HOURS 74: return 75: end 76: 77: if(revs.length < CRITICAL_REVISION_SIZE) 78: # We can do more 79: multiplier *= 2 80: end 81: if(revs.length > 2*CRITICAL_REVISION_SIZE) 82: # We must do less 83: multiplier /= 2 84: end 85: 86: unless(revs.empty?) 87: point = backwards ? revs[0] : revs[-1] 88: end 89: poll(point, direction, multiplier, now, options, &proc) 90: end