NETRAVE/lib/utils/first_run_init.rb
VetheonGames e4df29b0c1 Implementing Thread-Safe Alert System with Ring Buffer
This commit introduces a significant enhancement to our Ruby program by implementing a thread-safe alert system using a ring buffer data structure.

New Classes:
1. Alert: This class is responsible for creating and displaying alerts in the Curses Text User Interface (TUI). It takes a message and severity level as arguments and uses these to display color-coded alerts to the user.

2. AlertQueueManager: This class manages the queues for alerts using a ring buffer data structure. It continuously checks the queue and displays alerts as they arrive. It uses a mutex lock to ensure thread safety when accessing the ring buffer.

3. RingBuffer: This class is a custom implementation of a ring buffer, also known as a circular buffer. It's a fixed-size buffer that effectively overwrites old data when it is full. The buffer size has been optimized to 2MB to balance memory usage and performance.

Modifications to Existing Methods:
The DatabaseManager class has been updated to integrate the new alert system. The methods in this class now create Alert instances and enqueue them in the AlertQueueManager instead of directly displaying alerts to the user. This change ensures that alerts are displayed in a thread-safe manner and allows for better control over the timing and order of alert displays.

Thread Safety Measures:
Mutex locks and condition variables have been used to synchronize access to the ring buffer and prevent race conditions. This ensures that only one thread can access the buffer at a time, preventing data corruption and ensuring the correct operation of the alert system.

Testing:
Rigorous testing has been conducted to validate the correct functioning of the new system and to handle edge cases. This includes tests for the correct display of alerts, the correct operation of the ring buffer, and the correct synchronization of threads.

Documentation:
Detailed comments have been added to the code to explain the purpose and operation of the new classes and methods. This documentation will serve as a valuable reference for future development and maintenance of the codebase.

This commit represents a significant improvement in the functionality and robustness of our Ruby program's alert system.
2023-07-05 12:35:20 -06:00

132 lines
4.0 KiB
Ruby

# frozen_string_literal: true
require 'curses'
require 'dynamic_curses_input'
require 'dotenv'
require_relative 'database_manager'
require_relative 'system_information_gather'
require_relative 'utilities'
require_relative 'alert_manager'
# first run class
class FirstRunInit
include Utilities
include Curses
def initialize(loggman, alert_queue_manager, db_manager = nil)
@loggman = loggman
@db_manager = db_manager
@alert_queue_manager = alert_queue_manager
end
def run
first_run_setup
end
def first_run_setup # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
db_details = ask_for_db_details
enc_pass = ENV['DB_PASSWORD']
enc_key = ENV['DB_SECRET_KEY']
dec_pass = decrypt_string_chacha20(enc_pass, enc_key)
until @db_manager.test_db_connection(ENV['DB_USERNAME'], dec_pass.to_s, ENV['DB_DATABASE'])
Curses.setpos(4, 0)
Curses.addstr("Whoops! We couldn't connect to the database with the details you provided. Please try again!")
Curses.refresh
new_db_details = ask_for_db_details
db_details.merge!(new_db_details) # Update db_details with new details
end
@db_manager.create_system_info_table
@db_manager.create_services_table
uplink_speed = @info_gatherer.ask_for_uplink_speed
downlink_speed = @info_gatherer.ask_for_downlink_speed
total_bandwidth = calculate_total_bandwidth(uplink_speed, downlink_speed)
services = @info_gatherer.ask_for_services
system_info = {
uplink_speed:,
downlink_speed:,
total_bandwidth:
}
@db_manager.store_system_info(system_info)
@db_manager.store_services(services)
end
def ask_for_db_details # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
@loggman.log_info('Asking for Database details...')
Curses.clear
Curses.setpos(1, 0)
Curses.addstr('Please enter your database username: ')
Curses.refresh
alert = Alert.new('This is a test alert', :error)
@alert_queue_manager.enqueue_alert(alert)
username = DCI.catch_input(true)
@loggman.log_info('Database Username entered!')
Curses.setpos(2, 0)
Curses.addstr('Please enter your database password: ')
Curses.refresh
Curses.noecho
password = DCI.catch_input(false)
@loggman.log_info('Database Password Stored Securely!')
Curses.echo
Curses.setpos(3, 0)
Curses.addstr('Please enter your database name: ')
Curses.refresh
database = DCI.catch_input(true)
@loggman.log_info('Database Name entered!')
# Generate a secret key
key = generate_key
@loggman.log_info('Secret Key Generated!')
# Encrypt the password
encrypted_password = encrypt_string_chacha20(password, key)
@loggman.log_info('Password Encrypted!')
db_details = { username:, password: encrypted_password, key:, database: }
write_db_details_to_config_file(db_details)
@loggman.log_info('Wiriting Database details to a file!')
end
def write_db_details_to_config_file(db_details) # rubocop:disable Metrics/MethodLength
# Write the database details to the .env file
File.open('.env', 'w') do |file|
file.puts %(DB_USERNAME="#{db_details[:username]}")
file.puts %(DB_PASSWORD="#{db_details[:password]}")
file.puts %(DB_SECRET_KEY="#{db_details[:key]}")
file.puts %(DB_DATABASE="#{db_details[:database]}")
end
@loggman.log_info('Database details saved! Reloading environment...')
# Load the .env file using dotenv
Dotenv.load
@loggman.log_info('Environment restarted!')
rescue StandardError => e
@loggman.log_error("Failed to write to .env file: #{e.message}")
end
def ask_for_default_mode
loop do
Curses.setpos(8, 0)
Curses.addstr('Please enter the default mode (TUI, GUI, or WebApp): ')
Curses.refresh
mode = Curses.getstr.strip.downcase
return mode if valid_mode?(mode)
Curses.setpos(9, 0)
Curses.addstr("Whoops! That didn't appear to be a valid mode. Please try again!")
Curses.refresh
end
end
def valid_mode?(mode)
%w[tui gui webapp].include?(mode)
end
end