Class: Bard::Api::App

Inherits:
Object
  • Object
show all
Defined in:
lib/bard/api/app.rb

Constant Summary collapse

DEPLOY_LOCK =
"tmp/bard-deploy.lock"
DEPLOY_COMMAND =
"flock -n #{DEPLOY_LOCK} -c 'git pull --ff-only origin master && bin/setup'"

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.backup_runnerObject

Runs the backup task out-of-band so the request returns immediately. Override to wire backups into a project's own job queue.



16
17
18
# File 'lib/bard/api/app.rb', line 16

def backup_runner
  @backup_runner ||= ->(task) { Thread.new { task.call } }
end

.deploy_runnerObject

bin/setup restarts Puma via procsd restartsystemctl --user restart, which SIGKILLs the app unit's whole cgroup. So the deploy can't run in this worker (or any plain child of it) — it'd be killed mid-deploy. We run it in its own systemd --user scope: a separate cgroup that survives the restart.



24
25
26
# File 'lib/bard/api/app.rb', line 24

def deploy_runner
  @deploy_runner ||= method(:spawn_detached_deploy)
end

Class Method Details

.spawn_detached_deploy(command) ⇒ Object



28
29
30
31
32
33
34
# File 'lib/bard/api/app.rb', line 28

def spawn_detached_deploy(command)
  pid = Process.spawn(
    "systemd-run", "--user", "--scope", "--collect", "--quiet", "bash", "-lc", command,
    :in => "/dev/null", %i[out err] => ["log/bard-deploy.log", "a"],
  )
  Process.detach(pid)
end

Instance Method Details

#call(env) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/bard/api/app.rb', line 40

def call(env)
  request = Rack::Request.new(env)
  method = request.request_method
  path = request.path_info

  case [method, path]
  when ["GET", "/health"]
    health(request)
  when ["POST", "/backups"]
    create_backup(request)
  when ["GET", "/backups/latest"]
    latest_backup(request)
  when ["GET", "/config"]
    config(request)
  when ["POST", "/deploy"]
    create_deploy(request)
  else
    not_found
  end
rescue => e
  json_response(500, { error: e.message })
end