parent
91fa281237
commit
48b648f46b
@ -1,11 +1,27 @@
|
||||
require_relative "spork"
|
||||
require_relative "runner"
|
||||
|
||||
class MockManager
|
||||
attr :path, :error, :last_status, :last_pid
|
||||
attr :path, :config, :error, :last_status, :last_pid, :prep_dir
|
||||
|
||||
def initialize(path)
|
||||
def initialize(path, config, cfg_counter_path)
|
||||
@error = nil
|
||||
unless File.exist? (path)
|
||||
Dir.mkdir(path)
|
||||
end
|
||||
@path = path
|
||||
@config = config
|
||||
cntr = 0
|
||||
|
||||
File.open(cfg_counter_path, "r+") do |f|
|
||||
f.flock(File::LOCK_EX)
|
||||
counter = f.gets.strip
|
||||
i_counter = counter.to_i
|
||||
i_counter = i_counter + 1
|
||||
f.puts("#{i_counter}")
|
||||
cnt = i_counter
|
||||
end
|
||||
tmp_name = (0...10).map { ("a".."z").to_a[rand(26)] }.join
|
||||
@prep_dir = File.join(path, "#{cntr}_#{tmp_name}")
|
||||
end
|
||||
end
|
||||
|
@ -0,0 +1,89 @@
|
||||
require "open3"
|
||||
|
||||
class Runner
|
||||
attr_reader :cmd, :exit_status, :stdout, :stderr, :pid
|
||||
|
||||
# Run a command, return runner instance
|
||||
# @param cmd [String,Array<String>] command to execute
|
||||
def self.run(*cmd)
|
||||
Runner.new(*cmd).run
|
||||
end
|
||||
|
||||
# Run a command, raise Runner::Error if it fails
|
||||
# @param cmd [String,Array<String>] command to execute
|
||||
# @raise [Runner::Error]
|
||||
def self.run!(*cmd)
|
||||
Runner.new(*cmd).run!
|
||||
end
|
||||
|
||||
# Run a command, return true if it succeeds, false if not
|
||||
# @param cmd [String,Array<String>] command to execute
|
||||
# @return [Boolean]
|
||||
def self.run?(*cmd)
|
||||
Runner.new(*cmd).run?
|
||||
end
|
||||
|
||||
Error = Class.new(StandardError)
|
||||
|
||||
# @param cmd [String,Array<String>] command to execute
|
||||
def initialize(cmd)
|
||||
@cmd = cmd.is_a?(Array) ? cmd.join(" ") : cmd
|
||||
@stdout = +""
|
||||
@stderr = +""
|
||||
@exit_status = nil
|
||||
end
|
||||
|
||||
# @return [Boolean] success or failure?
|
||||
def success?
|
||||
exit_status.zero?
|
||||
end
|
||||
|
||||
# Run the command, return self
|
||||
# @return [Runner]
|
||||
def run
|
||||
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
|
||||
until [stdout, stderr].all?(&:eof?)
|
||||
readable = IO.select([stdout, stderr])
|
||||
next unless readable&.first
|
||||
|
||||
readable.first.each do |stream|
|
||||
data = +""
|
||||
# rubocop:disable Lint/HandleExceptions
|
||||
begin
|
||||
stream.read_nonblock(1024, data)
|
||||
rescue EOFError
|
||||
# ignore, it's expected for read_nonblock to raise EOFError
|
||||
# when all is read
|
||||
end
|
||||
|
||||
if stream == stdout
|
||||
@stdout << data
|
||||
$stdout.write(data)
|
||||
else
|
||||
@stderr << data
|
||||
$stderr.write(data)
|
||||
end
|
||||
end
|
||||
end
|
||||
@exit_status = wait_thr.value.exitstatus
|
||||
@pid = wait_thr.pid
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
# Run the command and return stdout, raise if fails
|
||||
# @return stdout [String]
|
||||
# @raise [Runner::Error]
|
||||
def run!
|
||||
return run.stdout if run.success?
|
||||
|
||||
raise(Error, "command failed, exit: %d - stdout: %s / stderr: %s" % [exit_status, stdout, stderr])
|
||||
end
|
||||
|
||||
# Run the command and return true if success, false if failure
|
||||
# @return success [Boolean]
|
||||
def run?
|
||||
run.success?
|
||||
end
|
||||
end
|
@ -0,0 +1,80 @@
|
||||
# A way to cleanly handle process forking in Sinatra when using Passenger, aka "sporking some code".
|
||||
# This will allow you to properly execute some code asynchronously, which otherwise does not work correctly.
|
||||
#
|
||||
# Written by Ron Evans
|
||||
# More info at http://deadprogrammersociety.com
|
||||
#
|
||||
# Mostly lifted from the Spawn plugin for Rails (http://github.com/tra/spawn)
|
||||
# but with all of the Rails stuff removed.... cause you are using Sinatra. If you are using Rails, Spawn is
|
||||
# what you need. If you are using something else besides Sinatra that is Rack-based under Passenger, and you are having trouble with
|
||||
# asynch processing, let me know if spork helped you.
|
||||
#
|
||||
module Spork
|
||||
# things to close in child process
|
||||
@@resources = []
|
||||
def self.resources
|
||||
@@resources
|
||||
end
|
||||
|
||||
# set the resource to disconnect from in the child process (when forking)
|
||||
def self.resource_to_close(resource)
|
||||
@@resources << resource
|
||||
end
|
||||
|
||||
# close all the resources added by calls to resource_to_close
|
||||
def self.close_resources
|
||||
@@resources.each do |resource|
|
||||
resource.close if resource && resource.respond_to?(:close) && !resource.closed?
|
||||
end
|
||||
@@resources = []
|
||||
end
|
||||
|
||||
# actually perform the fork... er, spork
|
||||
# valid options are:
|
||||
# :priority => to set the process priority of the child
|
||||
# :logger => a logger object to use from the child
|
||||
# :no_detach => true if you want to keep the child process under the parent control. usually you do NOT want this
|
||||
def self.spork(options = {})
|
||||
logger = options[:logger]
|
||||
logger.debug "spork> parent PID = #{Process.pid}" if logger
|
||||
child = fork do
|
||||
begin
|
||||
start = Time.now
|
||||
logger.debug "spork> child PID = #{Process.pid}" if logger
|
||||
|
||||
# set the nice priority if needed
|
||||
Process.setpriority(Process::PRIO_PROCESS, 0, options[:priority]) if options[:priority]
|
||||
|
||||
# disconnect from the rack
|
||||
Spork.close_resources
|
||||
|
||||
# run the block of code that takes so long
|
||||
yield
|
||||
rescue => ex
|
||||
logger.error "spork> Exception in child[#{Process.pid}] - #{ex.class}: #{ex.message}" if logger
|
||||
ensure
|
||||
logger.info "spork> child[#{Process.pid}] took #{Time.now - start} sec" if logger
|
||||
# this form of exit doesn't call at_exit handlers
|
||||
exit!(0)
|
||||
end
|
||||
end
|
||||
|
||||
# detach from child process (parent may still wait for detached process if they wish)
|
||||
Process.detach(child) unless options[:no_detach]
|
||||
|
||||
return child
|
||||
end
|
||||
end
|
||||
|
||||
# Patch to work with passenger
|
||||
if defined? Passenger::Rack::RequestHandler
|
||||
class Passenger::Rack::RequestHandler
|
||||
alias_method :orig_process_request, :process_request
|
||||
|
||||
def process_request(env, input, output)
|
||||
Spork.resource_to_close(input)
|
||||
Spork.resource_to_close(output)
|
||||
orig_process_request(env, input, output)
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,47 @@
|
||||
<%= erb :header %>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<h3 class="bg-secondary-subtle text-center border-bottom border-primary-subtle rounded-1 pb-1 mb-2">
|
||||
<a href="/prjedit/<%= ERB::Util.url_encode(@proj_id) %>"><%= @proj_name %></a>
|
||||
</h3>
|
||||
<div class="pb-2"><%= @proj_descr %></div>
|
||||
<div class="pb-2">git репозиторий <%= @git_name %></div>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<div class="hstack gap-3">
|
||||
<div class="p-2">Процесс сборки</div>
|
||||
<div><button type="button" class="btn btn-outline-primary" id="startBtn"><i
|
||||
class="bi bi-play-fill"></i></button>
|
||||
</div>
|
||||
<div><button type="button" class="btn btn-outline-primary" id="stopBtn"><i
|
||||
class="bi bi-pause-fill"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ratio ratio-4x3">
|
||||
<iframe src="/" title="Процесс сборки" id="bldframe" allowfullscreen></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
var intervalId = null;
|
||||
$(function () {
|
||||
intervalId = setInterval(refreshiframe, 5000);
|
||||
});
|
||||
function refreshiframe() {
|
||||
$('#bldframe').attr('src', $('#bldframe').attr('src'));
|
||||
}
|
||||
$("#startBtn").click(function () {
|
||||
if (intervalId == null) {
|
||||
intervalId = setInterval(refreshiframe, 5000);
|
||||
}
|
||||
})
|
||||
$("#stopBtn").click(function () {
|
||||
if (intervalId != null) {
|
||||
clearInterval(intervalId);
|
||||
intervalId = null;
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<%= erb :footer %>
|
Loading…
Reference in new issue