Module: RSCM::RevisionPoller

Included in:
Base
Defined in:
lib/rscm/revision_poller.rb

Constant Summary collapse

CRITICAL_REVISION_SIZE =

This is the number of revisions we’ll try to stick to for each call to revisions.

100
BASE_INCREMENT =

1 hour

60*60
TWENTY_FOUR_HOURS =
24*60*60

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#loggerObject

Returns the value of attribute logger.



3
4
5
# File 'lib/rscm/revision_poller.rb', line 3

def logger
  @logger
end

Instance Method Details

#poll(point = nil, direction = :backwards, multiplier = 1, now = Time.now.utc, options = {}, &proc) ⇒ Object

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.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/rscm/revision_poller.rb', line 29

def poll(point=nil, direction=:backwards, multiplier=1, now=Time.now.utc, options={}, &proc)
  raise "A block of arity 1 must be called" if proc.nil?
  backwards = direction == :backwards      
  point ||= now
  
  if point.respond_to?(:time)
    point_time = backwards ? point.time(:min) : point.time(:max)
    point_identifier = backwards ? point.identifier(:min) : point.identifier(:max)
  elsif point.is_a?(Time)
    point_time = point
    point_identifier = point
  else
    point_time = now
    point_identifier = point
  end

  increment = multiplier * BASE_INCREMENT
  if backwards
    to = point_identifier
    begin
      from = point_time - increment
    rescue ArgumentError
      from = Time.epoch
    end
    from = Time.epoch if from < Time.epoch
  else
    from = point_identifier
    begin
      to = point_time + increment
    rescue RangeError
      raise "RSCM will not work this far in the future (#{from} plus #{increment})"
    end
  end

  options = options.merge({:to_identifier => to})

  revs = revisions(from, options)
  raise "Got nil revision for from=#{from.inspect}" if revs.nil?
  revs.sort!
  proc.call(revs)

  if from == Time.epoch
    return
  end
  if !backwards and to.is_a?(Time) and (to) > now + TWENTY_FOUR_HOURS
    return
  end

  if(revs.length < CRITICAL_REVISION_SIZE)
    # We can do more
    multiplier *= 2
  end
  if(revs.length > 2*CRITICAL_REVISION_SIZE)
    # We must do less
    multiplier /= 2
  end

  unless(revs.empty?)
    point = backwards ? revs[0] : revs[-1]
  end
  poll(point, direction, multiplier, now, options, &proc)
end