class Scratch
Scratch randomly kills victim processes.
Like a cat scratching furniture, this chaos operation randomly terminates victim processes to test resilience and recovery.
Definitions
def initialize(interval: 60, probability: 0.1, signal: :TERM)
Create a new scratch chaos operation.
Signature
-
parameter
intervalInteger How often to check for chaos opportunities.
-
parameter
probabilityFloat Probability (0.0 to 1.0) of causing chaos on each check.
-
parameter
signalSymbol The signal to send when scratching.
Implementation
def initialize(interval: 60, probability: 0.1, signal: :TERM)
@interval = interval
@probability = probability
@signal = signal
@victims = Set.new.compare_by_identity
end
attr_reader :victims
Signature
-
attribute
Set The set of registered victims.
def register(chaos_controller)
Register a victim with the scratch chaos.
Signature
-
parameter
chaos_controllerChaosController The chaos controller for the victim.
Implementation
def register(chaos_controller)
Console.debug(self, "😺 Registering victim for scratch chaos.", id: chaos_controller.id)
@victims.add(chaos_controller)
end
def remove(chaos_controller)
Remove a victim from the scratch chaos.
Signature
-
parameter
chaos_controllerChaosController The chaos controller for the victim.
Implementation
def remove(chaos_controller)
@victims.delete(chaos_controller)
end
def status
Get status for the scratch chaos.
Signature
-
returns
Hash Status including victim count and configuration.
Implementation
def status
{
scratch: {
victims: @victims.size,
probability: @probability,
signal: @signal
}
}
end
def unleash_scratch
Unleash a scratch on a random victim.
Implementation
def unleash_scratch
return if @victims.empty?
# Pick a random victim
victim = @victims.to_a.sample
return unless victim
# Check probability
return unless rand < @probability
process_id = victim.process_id
return unless process_id
Console.info(self, "😾 *SCRATCH* Taking down a victim!", id: victim.id, process_id: process_id, signal: @signal)
begin
Process.kill(@signal, process_id)
rescue Errno::ESRCH
Console.warn(self, "Process already gone!", process_id: process_id)
rescue => error
Console.error(self, "Failed to scratch victim!", process_id: process_id, exception: error)
end
end
def run
Run the scratch chaos operation.
Signature
-
returns
Async::Task The task that is running the scratch chaos.
Implementation
def run
Async do
Loop.run(interval: @interval) do
unleash_scratch
end
end
end