Class: Xshellz::JobHandle

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

Overview

A background process started with Sandbox#spawn (or listed by Sandbox#jobs).

The process runs detached inside the sandbox (+nohup+, disowned) and its combined stdout+stderr goes to log_path (+~/.xshellz/jobs/.log+ in the box). The handle survives SDK restarts: Sandbox#jobs rebuilds handles from the pid files the spawn command leaves behind.

Constant Summary collapse

STOP_POLL_INTERVAL =
0.2

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sandbox:, id:, pid:) ⇒ JobHandle

Returns a new instance of JobHandle.



23
24
25
26
27
28
# File 'lib/xshellz/job_handle.rb', line 23

def initialize(sandbox:, id:, pid:)
  @sandbox = sandbox
  @id = id
  @pid = Integer(pid)
  @log_path = "~/.xshellz/jobs/#{id}.log"
end

Instance Attribute Details

#idObject (readonly)

Short job id (name-prefixed when spawn was given a name).



15
16
17
# File 'lib/xshellz/job_handle.rb', line 15

def id
  @id
end

#log_pathObject (readonly)

Path of the job's log file inside the sandbox.



21
22
23
# File 'lib/xshellz/job_handle.rb', line 21

def log_path
  @log_path
end

#pidObject (readonly)

Pid of the detached process inside the sandbox.



18
19
20
# File 'lib/xshellz/job_handle.rb', line 18

def pid
  @pid
end

Instance Method Details

#inspectObject Also known as: to_s



56
57
58
# File 'lib/xshellz/job_handle.rb', line 56

def inspect
  "#<Xshellz::JobHandle id=#{id.inspect} pid=#{pid} log=#{log_path.inspect}>"
end

#logs(tail_lines: 100) ⇒ Object

The last tail_lines lines of the job's log (stdout+stderr combined).



36
37
38
# File 'lib/xshellz/job_handle.rb', line 36

def logs(tail_lines: 100)
  @sandbox.run("tail -n #{Integer(tail_lines)} #{log_path} 2>/dev/null").stdout
end

#running?Boolean

Live probe: is the process still running? (+kill -0+ inside the box.)

Returns:

  • (Boolean)


31
32
33
# File 'lib/xshellz/job_handle.rb', line 31

def running?
  @sandbox.run("kill -0 #{pid} 2>/dev/null").ok?
end

#stop(grace: 5) ⇒ Object

Stop the job: SIGTERM, then SIGKILL if it is still alive after grace seconds. Returns true when the process exited from the SIGTERM alone.



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

def stop(grace: 5)
  @sandbox.run("kill -TERM #{pid} 2>/dev/null")
  deadline = monotonic + grace
  loop do
    return true unless running?

    if monotonic >= deadline
      @sandbox.run("kill -KILL #{pid} 2>/dev/null")
      return false
    end
    sleep(STOP_POLL_INTERVAL)
  end
end