Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@
/public/packs-test
/node_modules
/spec/examples.txt

/config/credentials/development.key

/config/credentials/test.key

/config/credentials/production.key
11 changes: 11 additions & 0 deletions app/controllers/pitboss_entries_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class PitbossEntriesController < ApplicationController
skip_before_action :verify_authenticity_token
before_action :authenticate_with_password, only: [:create]

def index
@pitboss_entries = PitbossEntry.order("id ASC").paginate(page: params[:page], per_page: 30)
Expand All @@ -12,6 +13,16 @@ def create

private

def authenticate_with_password
expected_password = Rails.application.credentials.pitboss_entries_password

return head :unauthorized unless expected_password

authenticate_or_request_with_http_basic do |username, password|
password == expected_password
end
end

def pitboss_entry_params
params.require(:pitboss_entry).permit(:game_name, :entry_type, :value, :timestamp)
end
Expand Down
1 change: 1 addition & 0 deletions config/credentials/development.yml.enc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
w5bT8eQYGizNXDKFUrYlXbvZIDbddrbJiN4qarVgHDgsq0EuWb2aJPTKnZ5IpyT0KsDuQOkezZucHs2pIvL05PkXpPq++s/R9Liq7mk4F67+bpC8gs7tDnFQKMH+K4d1iD3j3ujCaB2KfH6LgFDDD/Ra--u9XjoFdxLJzb9NB3--74vhM3pmCx6gqfgMXV4LUQ==
1 change: 1 addition & 0 deletions config/credentials/production.yml.enc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GOM2YhEQ5YUWCKZr9YAOssSye2uYmXEKz2BmPxj2TinRE9yo+N1NNWhMsiACyWjXmLeOtmSOEKGBos1GhjGBTg4UPuTN8P8mfGqagA8fiFV39kEc+aSmbO6QpBk8HYY0C/rP8bLZ5m19ULGy8GfAlHPLLhlppHEQ6bMaWjtQ1qoGzU975n3aiCKPK62PlUPHQTMHUhpn9TKSTjl2mgO3sTQCDSuCQ8bQRpPBI1Sb0TwVvsPSMpIUMWPU7VyH1DpGK2Yp8MdKluevTwesNCJi+8AtOkkpJgTyUgIt--zN3Bu6CmDiXo7sQy--UFC0/xxK2zC3ppMIB00xVw==
1 change: 1 addition & 0 deletions config/credentials/test.yml.enc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BvuC1bI4KFd3/SJGYOGD8JVIDqJOjidd0f/gUtabTB/ph/s7L5QgqfocT1mhreIUzng1GPeIl4cwKUKIM1+C7cu4AEyXPLKi1FpG4CRqKrSBmRSrvy38KwiTLmPTxB1EbJYuDTTq4Npzvkc=--6BYbTULSIbs+nYkl--GBBeNObL80Kq5eHldhyJ+Q==
10 changes: 8 additions & 2 deletions logs_parser/lib/logs_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ class HttpAdapter
NetworkError = Class.new(StandardError)
ServerError = Class.new(StandardError)

def initialize(host:)
def initialize(host:, password: nil)
@http = Net::HTTP.new(host)
@password = password
end

def send_data(payload)
Expand All @@ -87,6 +88,11 @@ def send_data(payload)
"pitboss_entry[timestamp]" => payload.timestamp
}
)

if @password
request.basic_auth("", @password)
end

response = http.request(request)
raise ServerError, response.code unless response.code_type == Net::HTTPNoContent
return response
Expand All @@ -104,6 +110,6 @@ def send_data(payload)

private

attr_reader :http
attr_reader :http, :password
end
end
152 changes: 152 additions & 0 deletions script/pbs5.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
require "net/http"
require_relative "../logs_parser/lib/logs_parser"

class LogFileMonitor
def initialize(log_file_path, initial_position = 0)
@log_file_path = log_file_path
@file_position = initial_position
@last_size = 0
@last_mtime = Time.at(0)
@file_handle = nil
end

def file_changed?
return false unless File.exist?(@log_file_path)

stat = File.stat(@log_file_path)
size_changed = stat.size != @last_size
mtime_changed = stat.mtime != @last_mtime

@last_size = stat.size
@last_mtime = stat.mtime

size_changed || mtime_changed
end

def file_rotated?
return false unless File.exist?(@log_file_path)

stat = File.stat(@log_file_path)
stat.size < @file_position
end

def read_new_lines
return [] unless File.exist?(@log_file_path)

if file_rotated?
puts "Log file rotated, starting from beginning"
@file_position = 0
close_file
end

open_file
@file_handle.seek(@file_position)

new_lines = []
while line = @file_handle.gets
new_lines << line.chomp
end

@file_position = @file_handle.tell
new_lines
end

def close
close_file
end

private

def open_file
unless @file_handle && !@file_handle.closed?
@file_handle = File.open(@log_file_path, "r")
end
end

def close_file
if @file_handle && !@file_handle.closed?
@file_handle.close
@file_handle = nil
end
end
end

def main
if ARGV.length < 3
puts "Usage: ruby pbs5.rb <game_name> <players_count> <pitboss_entries_password> [initial_position] [host]"
puts "Example: ruby pbs5.rb my_game 4 secret_password 0 fierce-reaches-40697.herokuapp.com"
exit 1
end

game_name = ARGV[0]
players_count = ARGV[1].to_i
password = ARGV[2]
initial_position = ARGV[3].to_i || 0
host = ARGV[4] || "fierce-reaches-40697.herokuapp.com"
log_file_path = "net_message_debug.log"

unless game_name && players_count > 0 && password
puts "Error: game_name, players_count, and password are required"
exit 1
end

parser = LogsParser::Service.new(game_name, players_count)
http_adapter = LogsParser::HttpAdapter.new(host: host, password: password)
monitor = LogFileMonitor.new(log_file_path, initial_position)

iterations_counter = 0
processed_lines = 0

puts "Starting log monitor for #{game_name} (#{players_count} players)"
puts "Initial position: #{initial_position}"
puts "Host: #{host}"
puts "Authentication: enabled"

begin
loop do
iterations_counter += 1

if monitor.file_changed?
puts "Iteration #{iterations_counter} - File changed, processing new lines..."

new_lines = monitor.read_new_lines

if new_lines.empty?
puts "No new lines to process"
else
puts "Processing #{new_lines.count} new lines..."

new_lines.each do |line|
begin
if result = parser.call(line)
response = http_adapter.send_data(result)
puts "Sent: #{result.entry_type} - #{response.code}"
processed_lines += 1
end
rescue LogsParser::HttpAdapter::NetworkError, LogsParser::HttpAdapter::ServerError => e
puts "Error sending data: #{e.class} - #{e.message}"
puts "Will retry on next iteration"
end
end
end

puts "Current position: #{monitor.instance_variable_get(:@file_position)}"
puts "Total processed lines: #{processed_lines}"
else
puts "Iteration #{iterations_counter} - No changes detected"
end

sleep 5
end
rescue Interrupt
puts "\nShutting down gracefully..."
ensure
monitor.close
puts "Final position: #{monitor.instance_variable_get(:@file_position)}"
puts "Total processed lines: #{processed_lines}"
end
end

if __FILE__ == $0
main
end
Loading