Class: Dbd::TimeStamp

Inherits:
Object
  • Object
show all
Defined in:
lib/dbd/time_stamp.rb

Overview

TimeStamp

Each Fact has a time_stamp with a granularity of 1 ns. The small granularity is essential to allow enough "density" of Facts in a large fact stream. Since all Facts need to have a strictly monotonically increasing time_stamp, this causes a limitation of max 1_000_000_000 Facts per second in a fact stream.

A second reason for a fine grained granularity of the time_stamp is to reduce the chance (but not to zero) for collisions between Facts when 2 (or more) fact streams with overlapping time ranges need to be merged. But, collisions are always possible and need to be handled (since this can be expensive, we need to avoid them).

A practicaly problem with calculating a "randomized" time_stamp is that the system reports a Wall clock with a granularity of 1 us on MRI Ruby and only 1 ms on JRuby (see JSR 310). To solve this problem, some nifty tricks are needed to create more "randomized" time_stamps, while still guaranteeing, the strictly monotonic increase in an upredictable fact stream.

Performance measurements show a typical 30 - 60 us delay between the consecutive created facts (on MRI and JRuby), so a randomization of e.g. 1 - 999 ns should not cause fundamental problems for the density of the facts (even if computers speed up a factor of 30 or an implementation in a faster language). Still this is an ad-hoc optimization at creation time and can be optimized without breaking the specification of the fact stream.

A time_stamp does not need to represent the exact time of the creation of the fact, it only has to increase strictly monotic in a fact stream.

Constant Summary collapse

MAX_DRIFT =

Max drift in time_stamp

Rational("1/1_000_000")

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ TimeStamp

Builds a new TimeStamp.

Parameters:

  • options (Hash{Symbol => Object}) (defaults to: {})

Options Hash (options):

  • :time (Time, String) — default: Time.now —

    force the time to this value

  • :larger_than (TimeStamp) — default: void —

    time_stamp must be larger than this



47
48
49
50
# File 'lib/dbd/time_stamp.rb', line 47

def initialize(options={})
  @time = options[:time] || new_time(options[:larger_than])
  @time = time_from_s(@time) if @time.is_a?(String)
end

Instance Attribute Details

#time ⇒ Object (readonly)

Returns the value of attribute time.



39
40
41
# File 'lib/dbd/time_stamp.rb', line 39

def time
  @time
end

Class Method Details

.to_s_regexp ⇒ Object

regexp for the nanosecond granularity and in UTC

Can be used to validate input strings or in tests.



56
57
58
# File 'lib/dbd/time_stamp.rb', line 56

def self.to_s_regexp
  /\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\.\d{9} UTC/
end

Instance Method Details

#+(seconds) ⇒ Object



133
134
135
# File 'lib/dbd/time_stamp.rb', line 133

def +(seconds)
  self.class.new(time: (@time + seconds))
end

#-(other) ⇒ Object



137
138
139
# File 'lib/dbd/time_stamp.rb', line 137

def -(other)
  @time - other.time
end

#<(other) ⇒ Object



121
122
123
# File 'lib/dbd/time_stamp.rb', line 121

def <(other)
  @time < other.time
end

#<=(other) ⇒ Object



129
130
131
# File 'lib/dbd/time_stamp.rb', line 129

def <=(other)
  @time <= other.time
end

#>(other) ⇒ Object



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

def >(other)
  @time > other.time
end

#>=(other) ⇒ Object



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

def >=(other)
  @time >= other.time
end

#near?(other) ⇒ Boolean

determines if 2 time_stamps are "near".

The time_stamp of an equivalent fact may be slightly different (because shifts of a few nanoseconds will be required to resolve collisions on a merge of fact streams with overlapping time_stamp ranges).

Returns:

  • (Boolean)


113
114
115
# File 'lib/dbd/time_stamp.rb', line 113

def near?(other)
  (self - other).abs <= MAX_DRIFT
end

#to_s ⇒ Object

with a nanosecond granularity and in UTC



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

def to_s
  @time.strftime(time_format)
end