Class: Siding::Runtime

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

Defined Under Namespace

Classes: Unavailable

Constant Summary collapse

DIRECTORY_MODE =
0o700
NAMESPACE =
"siding"
FALLBACK_ROOT =

Used when XDG_RUNTIME_DIR is unset -- common on macOS, where there is no such convention. ~/.local/state is the XDG base-directory spec's home for state that should persist between restarts but is not configuration.

File.join(".local", "state", NAMESPACE)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_key:, root:) ⇒ Runtime

Returns a new instance of Runtime.



41
42
43
44
# File 'lib/siding/runtime.rb', line 41

def initialize(project_key:, root:)
  @project_key = project_key
  @root = root
end

Instance Attribute Details

#project_keyObject (readonly)

Returns the value of attribute project_key.



28
29
30
# File 'lib/siding/runtime.rb', line 28

def project_key
  @project_key
end

#rootObject (readonly)

Returns the value of attribute root.



28
29
30
# File 'lib/siding/runtime.rb', line 28

def root
  @root
end

Class Method Details

.for(project_key, env: ENV) ⇒ Object



30
31
32
# File 'lib/siding/runtime.rb', line 30

def self.for(project_key, env: ENV)
  new(project_key: project_key, root: root_for(env))
end

.process_alive?(pid) ⇒ Boolean

Returns:

  • (Boolean)


89
90
91
92
93
94
95
96
97
98
# File 'lib/siding/runtime.rb', line 89

def self.process_alive?(pid)
  Process.kill(0, pid)
  true
rescue Errno::ESRCH, Errno::EPERM
  false
rescue SystemCallError
  # Anything else means the question could not be asked, and a live process wrongly called dead
  # would have us boot a second server over a working one.
  true
end

.root_for(env) ⇒ Object



34
35
36
37
38
39
# File 'lib/siding/runtime.rb', line 34

def self.root_for(env)
  xdg = env["XDG_RUNTIME_DIR"]
  return File.join(xdg, NAMESPACE) if xdg && !xdg.empty?

  File.join(Dir.home, FALLBACK_ROOT)
end

Instance Method Details

#boot_log_pathObject



50
# File 'lib/siding/runtime.rb', line 50

def boot_log_path = File.join(dir, "boot.log")

#dirObject



46
# File 'lib/siding/runtime.rb', line 46

def dir = File.join(root, project_key.digest)

#discard_recordsObject



80
81
82
83
84
85
86
87
# File 'lib/siding/runtime.rb', line 80

def discard_records
  [socket_path, server_info_path].each do |path|
    File.unlink(path)
  rescue SystemCallError
    nil
  end
  true
end

#discard_socketObject



73
74
75
76
77
78
# File 'lib/siding/runtime.rb', line 73

def discard_socket
  File.unlink(socket_path)
  true
rescue SystemCallError
  false
end

#events_pathObject



51
# File 'lib/siding/runtime.rb', line 51

def events_path = File.join(dir, "events.jsonl")

#live_server_infoObject



61
62
63
64
65
66
67
68
69
# File 'lib/siding/runtime.rb', line 61

def live_server_info
  info = server_info
  return nil if info.nil?

  pid = info["pid"]
  return nil unless pid.is_a?(Integer) && self.class.process_alive?(pid)

  info
end

#lock_pathObject



48
# File 'lib/siding/runtime.rb', line 48

def lock_path = File.join(dir, "lock")

#log_pathObject



52
# File 'lib/siding/runtime.rb', line 52

def log_path = File.join(dir, "siding.log")

#prepareObject



100
101
102
103
104
105
# File 'lib/siding/runtime.rb', line 100

def prepare
  check_socket_path_length
  ensure_directory(root)
  ensure_directory(dir)
  self
end

#prepared?Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/siding/runtime.rb', line 107

def prepared?
  File.directory?(dir) && safe_directory?(dir) && socket_path_within_limit?
end

#server_infoObject



54
55
56
57
58
59
# File 'lib/siding/runtime.rb', line 54

def server_info
  info = JSON.parse(File.read(server_info_path))
  info.is_a?(Hash) ? info : nil
rescue SystemCallError, JSON::ParserError
  nil
end

#server_info_pathObject



49
# File 'lib/siding/runtime.rb', line 49

def server_info_path = File.join(dir, "server.json")

#server_pidObject



71
# File 'lib/siding/runtime.rb', line 71

def server_pid = live_server_info&.[]("pid")

#socket_pathObject



47
# File 'lib/siding/runtime.rb', line 47

def socket_path = File.join(dir, "sock")

#socket_path_within_limit?Boolean

Returns:

  • (Boolean)


118
119
120
# File 'lib/siding/runtime.rb', line 118

def socket_path_within_limit?
  socket_path.bytesize <= Platform::UNIX_SOCKET_PATH_LIMIT - 1
end

#unavailable_reasonObject



111
112
113
114
115
116
# File 'lib/siding/runtime.rb', line 111

def unavailable_reason
  prepare
  nil
rescue Unavailable => e
  e.message
end