Class: CycleTimeConfig

Inherits:
Object
  • Object
show all
Includes:
SelfOrIssueDispatcher
Defined in:
lib/jirametrics/cycle_time_config.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from SelfOrIssueDispatcher

#method_missing, #respond_to_missing?

Constructor Details

#initialize(possible_statuses:, label:, block:, settings:, file_system: nil, today: Date.today) ⇒ CycleTimeConfig

Returns a new instance of CycleTimeConfig.



11
12
13
14
15
16
17
18
19
20
21
# File 'lib/jirametrics/cycle_time_config.rb', line 11

def initialize possible_statuses:, label:, block:, settings:, file_system: nil, today: Date.today
  @possible_statuses = possible_statuses
  @label = label
  @today = today
  @settings = settings

  # If we hit something deprecated and this is nil then we'll blow up. Although it's ugly, this
  # may make it easier to find problems in the test code ;-)
  @file_system = file_system
  instance_eval(&block) unless block.nil?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class SelfOrIssueDispatcher

Instance Attribute Details

#file_systemObject (readonly)

Returns the value of attribute file_system.



9
10
11
# File 'lib/jirametrics/cycle_time_config.rb', line 9

def file_system
  @file_system
end

#labelObject (readonly)

Returns the value of attribute label.



9
10
11
# File 'lib/jirametrics/cycle_time_config.rb', line 9

def label
  @label
end

#settingsObject (readonly)

Returns the value of attribute settings.



9
10
11
# File 'lib/jirametrics/cycle_time_config.rb', line 9

def settings
  @settings
end

Instance Method Details

#age(issue, today: nil) ⇒ Object



109
110
111
112
113
114
115
# File 'lib/jirametrics/cycle_time_config.rb', line 109

def age issue, today: nil
  start = started_stopped_times(issue).first
  stop = today || @today || Date.today
  return nil if start.nil? || stop.nil?

  (stop.to_date - start.to_date).to_i + 1
end

#collapse_zero_length_start(started, stopped) ⇒ Object

When start and stop land on the same instant, treat the issue as stopped-but-never-started so a zero-length span doesn't conflict with 'in or right of' start logic.



73
74
75
76
77
# File 'lib/jirametrics/cycle_time_config.rb', line 73

def collapse_zero_length_start started, stopped
  return nil if started&.time == stopped&.time

  started
end

#cycletime(issue) ⇒ Object



102
103
104
105
106
107
# File 'lib/jirametrics/cycle_time_config.rb', line 102

def cycletime issue
  start, stop = started_stopped_times(issue)
  return nil if start.nil? || stop.nil?

  (stop.to_date - start.to_date).to_i + 1
end

#done?(issue) ⇒ Boolean

Returns:

  • (Boolean)


38
39
40
# File 'lib/jirametrics/cycle_time_config.rb', line 38

def done? issue
  started_stopped_times(issue).last
end

#flush_cacheObject



93
94
95
# File 'lib/jirametrics/cycle_time_config.rb', line 93

def flush_cache
  @cache = nil
end

#in_progress?(issue) ⇒ Boolean

Returns:

  • (Boolean)


33
34
35
36
# File 'lib/jirametrics/cycle_time_config.rb', line 33

def in_progress? issue
  started_time, stopped_time = started_stopped_times(issue)
  started_time && stopped_time.nil?
end

#possible_statusesObject



117
118
119
120
121
122
123
124
125
# File 'lib/jirametrics/cycle_time_config.rb', line 117

def possible_statuses
  if parent_config.is_a? BoardConfig
    project_config = parent_config.project_config
  else
    # TODO: This will go away when cycletimes are no longer supported inside html_reports
    project_config = parent_config.file_config.project_config
  end
  project_config.possible_statuses
end

#resolve_change(block, issue) ⇒ Object

start_at/stop_at blocks must return a ChangeItem or nil. A legacy false (meaning "not found") is still tolerated as nil, but a bare Time -- once accepted and wrapped -- is no longer supported.



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

def resolve_change block, issue
  change = block.call(issue)
  return nil unless change

  unless change.is_a?(ChangeItem)
    raise "A start_at/stop_at block must return a ChangeItem or nil but returned a #{change.class}. " \
      'If you were relying on a bare time such as `created`, use the ChangeItem form (e.g. `time_created`).'
  end

  change
end

#start_at(block = nil) ⇒ Object



23
24
25
26
# File 'lib/jirametrics/cycle_time_config.rb', line 23

def start_at block = nil
  @start_at = block unless block.nil?
  @start_at
end

#started_stopped_changes(issue) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/jirametrics/cycle_time_config.rb', line 42

def started_stopped_changes issue
  cache_key = "#{issue.key}:#{issue.board.id}"
  last_result = (@cache ||= {})[cache_key]
  return *last_result if last_result && settings['cache_cycletime_calculations']

  started = resolve_change(@start_at, issue)
  stopped = resolve_change(@stop_at, issue)
  started = collapse_zero_length_start(started, stopped)

  result = [started, stopped]
  warn_on_cache_mismatch(issue: issue, result: result, last_result: last_result)
  @cache[cache_key] = result
  result
end

#started_stopped_dates(issue) ⇒ Object



97
98
99
100
# File 'lib/jirametrics/cycle_time_config.rb', line 97

def started_stopped_dates issue
  started_time, stopped_time = started_stopped_times(issue)
  [started_time&.to_date, stopped_time&.to_date]
end

#started_stopped_times(issue) ⇒ Object



88
89
90
91
# File 'lib/jirametrics/cycle_time_config.rb', line 88

def started_stopped_times issue
  started, stopped = started_stopped_changes(issue)
  [started&.time, stopped&.time]
end

#stop_at(block = nil) ⇒ Object



28
29
30
31
# File 'lib/jirametrics/cycle_time_config.rb', line 28

def stop_at block = nil
  @stop_at = block unless block.nil?
  @stop_at
end

#warn_on_cache_mismatch(issue:, result:, last_result:) ⇒ Object



79
80
81
82
83
84
85
86
# File 'lib/jirametrics/cycle_time_config.rb', line 79

def warn_on_cache_mismatch issue:, result:, last_result:
  return unless last_result && result != last_result

  @file_system.error(
    "Calculation mismatch; this could break caching. #{issue.inspect} new=#{result.inspect}, " \
      "previous=#{last_result.inspect}"
  )
end