Class: Unravel::Session

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

Defined Under Namespace

Classes: FixableError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSession

Returns a new instance of Session.



89
90
91
# File 'lib/unravel.rb', line 89

def initialize
  @registry = Registry.new
end

Instance Attribute Details

#registryObject (readonly)

Returns the value of attribute registry.



80
81
82
# File 'lib/unravel.rb', line 80

def registry
  @registry
end

Instance Method Details

#achieve(name, max_retries = 5) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/unravel.rb', line 93

def achieve(name, max_retries = 5)
  check # TODO: overhead?

  prev_causes = Set.new
  retries_left = max_retries

  begin
    Unravel.logger.info("Achieving (attempt: #{max_retries - retries_left + 1}/#{max_retries}): #{name.inspect}")

    block = registry.get_achievement(name)
    error_contexts = registry.error_contexts_for_achievement(name)

    begin
      res = return_wrap(&block)
    rescue *error_contexts.keys
      ex = $!
      econtext = error_contexts[ex.class]
      unless econtext
        # TODO: not tested
        fail "No error context given for #{name} to handle exception: #{ex.message}"
      end

      econtext.each do |fix_name|
        error = $!.message
        fix! fix_name, error
      end
      fail
    end

    return true if res == true
    fail NotImplementedError, "#{name} unexpectedly returned #{res.inspect} (expected true or exception)"

  rescue FixableError => error
    Unravel.logger.info("#{name}: Symptom: #{error.symptom.inspect}")

    #Unravel.logger.debug("  -> failed: #{name.inspect}: #{error.symptom.inspect}\n")
    cause = get_root_cause_for(error.symptom)

    fail NoKnownRootCause, "Can't find root cause for: #{error.symptom}, #{error.message}" unless cause

    Unravel.logger.info("#{name}: Cause: #{cause.inspect}")
    if prev_causes.include? cause
      fail SameCauseReoccurringCause, "#{cause.to_s} wasn't ultimately fixed (it occured again)"
    end

    prev_causes << cause
    recipe_for(cause).call

    retries_left -= 1
    retry if retries_left > 0
    fail
  end
end

#achievement(name, error_contexts, &block) ⇒ Object



147
148
149
150
# File 'lib/unravel.rb', line 147

def achievement(name, error_contexts, &block)
  registry.add_achievement(name, &block)
  registry.add_error_contexts(name, error_contexts)
end

#errorObject



152
153
154
# File 'lib/unravel.rb', line 152

def error
  registry.errors
end

#fix_for(*args, &block) ⇒ Object

TODO: move logic to registry



162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/unravel.rb', line 162

def fix_for(*args, &block)
  name, achievement = *args
  if block_given?
    if args.size > 1
      fail ArgumentError, "#{args[1..-1].inspect} ignored because of block"
    end
    registry.add_fix(name, block)
  else
    if name.is_a?(Hash)
      name, achievement = *name.first
    end
    fix_for(name) { achieve achievement } unless block_given?
  end
end

#quickfix(error_name, regexp, fix_name, handlers = {}) ⇒ Object

Shorthand for easy-to-fix and name problems



178
179
180
181
182
183
184
# File 'lib/unravel.rb', line 178

def quickfix(error_name, regexp, fix_name, handlers={})
  root_cause_name = "no_#{fix_name}".to_sym
  error[error_name] = regexp
  root_cause_for error_name => root_cause_name
  fix_for root_cause_name =>  fix_name
  achievement fix_name, handlers, &method(fix_name)
end

#root_cause_for(mapping) ⇒ Object



156
157
158
159
# File 'lib/unravel.rb', line 156

def root_cause_for(mapping)
  symptom, root_cause = *mapping.first
  registry.add_symptom(symptom, root_cause)
end