class Pgtk::PgsqlTask

Pgsql rake task.

Author

Yegor Bugayenko (yegor256@gmail.com)

Copyright

Copyright © 2019 Yegor Bugayenko

License

MIT

Attributes

dbname[RW]
dir[RW]
fresh_start[RW]
name[RW]
password[RW]
port[RW]
quiet[RW]
user[RW]
yaml[RW]

Public Class Methods

new(*args) { |*[self, task_args].slice(0, arity)| ... } click to toggle source
# File lib/pgtk/pgsql_task.rb, line 48
def initialize(*args, &task_block)
  @name = args.shift || :pgsql
  @fresh_start = false
  @quite = false
  @user = 'test'
  @password = 'test'
  @dbname = 'test'
  @port = nil
  unless ::Rake.application.last_description
    desc 'Start a local PostgreSQL server'
  end
  task(name, *args) do |_, task_args|
    RakeFileUtils.send(:verbose, true) do
      yield(*[self, task_args].slice(0, task_block.arity)) if block_given?
      run
    end
  end
end

Private Instance Methods

run() click to toggle source
# File lib/pgtk/pgsql_task.rb, line 69
def run
  raise "Option 'dir' is mandatory" unless @dir
  raise "Option 'yaml' is mandatory" unless @yaml
  home = File.expand_path(@dir)
  FileUtils.rm_rf(home) if @fresh_start
  if File.exist?(home)
    raise "Directory/file #{home} is present, use fresh_start=true"
  end
  out = "2>&1 #{@quiet ? '>/dev/null' : ''}"
  Tempfile.open do |pwfile|
    IO.write(pwfile.path, @password)
    system(
      [
        'initdb --auth=trust',
        "-D #{Shellwords.escape(home)}",
        '--username',
        Shellwords.escape(@user),
        '--pwfile',
        Shellwords.escape(pwfile.path),
        out
      ].join(' ')
    )
  end
  raise unless $CHILD_STATUS.exitstatus.zero?
  port = @port
  if port.nil?
    port = RandomPort::Pool::SINGLETON.acquire
    puts "Random TCP port #{port} is used"
  else
    puts "Required TCP port #{port} is used"
  end
  pid = Process.spawn('postgres', '-k', home, '-D', home, "--port=#{port}")
  IO.write(File.join(@dir, 'pid'), pid)
  at_exit do
    `kill -TERM #{pid}`
    puts "PostgreSQL killed in PID #{pid}"
  end
  sleep 1
  attempt = 0
  begin
    system(
      [
        "createdb -h localhost -p #{port}",
        '--username',
        Shellwords.escape(@user),
        Shellwords.escape(@dbname),
        out
      ].join(' ')
    )
    raise unless $CHILD_STATUS.exitstatus.zero?
  rescue StandardError => e
    puts e.message
    sleep(5)
    attempt += 1
    raise if attempt > 10
    retry
  end
  IO.write(
    @yaml,
    {
      'pgsql' => {
        'host' => 'localhost',
        'port' => port,
        'dbname' => @dbname,
        'user' => @user,
        'password' => @password,
        'url' => [
          "jdbc:postgresql://localhost:#{port}/",
          "#{CGI.escape(@dbname)}?user=#{CGI.escape(@user)}"
        ].join
      }
    }.to_yaml
  )
  puts "PostgreSQL has been started in process ##{pid}, port #{port}"
end