Ravn::Tactical::
ChangeRunner
class
Actor that continually tries to run pending changes on nodes in the current kit.
- LOOP_TIME
Number of seconds between runs
- thread R
The Thread that is started when running
Create a new ChangeRunner
.
44 def initialize
45 @thread = nil
46 @running = false
47 end
Start an instance of the ChangeRunner
and run it until all changes are completed.
38 def self::run_until_complete
39 self.new.run_until_complete
40 end
Start an instance of the ChangeRunner
and return the resulting Thread.
24 def self::start
25 @instance ||= self.new.start
26 return @instance.thread
27 end
Stop the running instance of the ChangeRunner
(if there is one)
31 def self::stop
32 @instance&.stop
33 end
Run the specified change
, returning a truthy value if it runs successfully.
149 def run_change( change )
150 op = change.operation
151
152 op.before_run( change.node )
153 response = Ravn::Tactical::Kit.run_change( change )
154 result = op.after_run( change.node, response )
155 self.log.debug "Result is: %p" % [ result ]
156
157 return result
158 rescue => err
159 self.log.error "%p while running %p: %s" % [ err.class, change, err.message ]
160 self.log.debug { err.backtrace.join("\n") }
161
162 return nil
163 end
Run any pending changes for nodes which are discoverable, skipping any that aren’t online.
102 def run_pending_changes
103 dataset = Ravn::Tactical::Change.earliest_for_each_node
104 start = Ravn.monotonic_time
105
106 self.log.info "Running %d pending changes" % [ dataset.count ]
107 dataset.each do |change|
108 node = change.node
109 node.update_discovery_info
110 next unless node.online?
111
112 self.log.info "running: %p" % [ change ]
113 self.try_change( change )
114 end
115
116 duration = Ravn.monotonic_time - start
117 self.log.debug " run took %0.5s" % [ duration ]
118
119 if (remainder = LOOP_TIME - duration) > 0
120 sleep( remainder )
121 end
122 end
Start running changes and exit once the queue is empty.
83 def run_until_complete
84 self.running = true
85 self.run_pending_changes until Ravn::Tactical::Change.empty?
86 self.running = false
87 end
True if the running is running.
60 attr_predicate_accessor :running
Start trying to run changes on visible CPs.
64 def start
65 self.log.info "Starting change runner."
66 @thread = Thread.new( &self.method(:start_running_changes) )
67
68 return self
69 end
Start trying to run pending changes.
91 def start_running_changes
92 Thread.current.name = "Change Runner loop" unless Thread.current == Thread.main
93
94 self.running = true
95
96 self.run_pending_changes while self.running?
97 end
Stop running changes.
73 def stop
74 self.log.info "Stopping change runner."
75 self.running = false
76
77 @thread.join( 2 ) if @thread&.alive?
78 @thread = nil
79 end
Try to run the given change
, removing it if it runs successfully.
126 def try_change( change )
127
128
129
130 change.db.transaction do
131 result = self.run_change( change )
132
133 if result
134 self.log.info "%p succeeded." % [ change ]
135 self.log.debug {
136 "Results:\n%p" % [ result ]
137 }
138 change.delete
139 else
140 self.log.error "%p failed." % [ change ]
141 raise Sequel::Rollback, "%p failed." % [ change ]
142 end
143 end
144 end