Module: Timet::DatabaseSyncer
- Included in:
- DatabaseSyncHelper
- Defined in:
- lib/timet/database_syncer.rb
Overview
Module responsible for synchronizing local and remote databases
Constant Summary collapse
- ITEM_FIELDS =
Fields used in item operations
%w[start end tag notes pomodoro updated_at created_at deleted].freeze
Instance Method Summary collapse
-
#format_status_message(id, item, source) ⇒ String
Formats item status message.
-
#get_item_values(item, include_id_at_start: false) ⇒ Array
Gets the values array for database operations.
-
#handle_database_differences(*args) ⇒ void
Handles the synchronization process when differences are detected between databases.
-
#handle_sync_error(error, remote_storage, bucket, local_db_path) ⇒ void
Handles errors that occur during database synchronization.
-
#insert_item_from_hash(db, item) ⇒ void
Inserts a new item into the database from a hash.
-
#items_to_hash(items) ⇒ Hash
Converts database items to a hash indexed by ID.
-
#open_remote_database(remote_path) ⇒ SQLite3::Database
Opens and validates a connection to the remote database.
-
#process_database_items(local_db, remote_db) ⇒ void
Processes items from both databases and syncs them.
-
#process_existing_item(*args) ⇒ Symbol
Processes an item that exists in both databases.
-
#remote_wins?(remote_item, remote_time, local_time) ⇒ Boolean
Determines if remote item should take precedence.
-
#sync_databases(*args) ⇒ void
Synchronizes the local and remote databases by comparing and merging their items.
-
#sync_items_by_id(local_db, local_items_by_id, remote_items_by_id) ⇒ void
Syncs items between local and remote databases based on their IDs.
-
#sync_with_remote_database(*args) ⇒ void
Performs the actual database synchronization by setting up connections and syncing data.
-
#update_item_from_hash(db, item) ⇒ void
Updates an existing item in the database with values from a hash.
Instance Method Details
#format_status_message(id, item, source) ⇒ String
Formats item status message
185 186 187 188 |
# File 'lib/timet/database_syncer.rb', line 185 def (id, item, source) deleted = item['deleted'].to_i == 1 ? ' and deleted' : '' "#{source} item #{id} is newer#{deleted} - #{source == 'Remote' ? 'updating local' : 'will be uploaded'}" end |
#get_item_values(item, include_id_at_start: false) ⇒ Array
Gets the values array for database operations
208 209 210 211 212 |
# File 'lib/timet/database_syncer.rb', line 208 def get_item_values(item, include_id_at_start: false) @database_fields ||= ITEM_FIELDS values = @database_fields.map { |field| item[field] } include_id_at_start ? [item['id'], *values] : values end |
#handle_database_differences(*args) ⇒ void
This method attempts to sync the databases and handles any errors that occur during the process
This method returns an undefined value.
Handles the synchronization process when differences are detected between databases
18 19 20 21 22 23 24 25 26 |
# File 'lib/timet/database_syncer.rb', line 18 def handle_database_differences(*args) local_db, remote_storage, bucket, local_db_path, remote_path = args puts 'Differences detected between local and remote databases' begin sync_with_remote_database(local_db, remote_path, remote_storage, bucket, local_db_path) rescue SQLite3::Exception => e handle_sync_error(e, remote_storage, bucket, local_db_path) end end |
#handle_sync_error(error, remote_storage, bucket, local_db_path) ⇒ void
When sync fails, this method falls back to uploading the local database
This method returns an undefined value.
Handles errors that occur during database synchronization
36 37 38 39 40 |
# File 'lib/timet/database_syncer.rb', line 36 def handle_sync_error(error, remote_storage, bucket, local_db_path) puts "Error opening remote database: #{error.}" puts 'Uploading local database to replace corrupted remote database' remote_storage.upload_file(bucket, local_db_path, 'timet.db') end |
#insert_item_from_hash(db, item) ⇒ void
This method returns an undefined value.
Inserts a new item into the database from a hash
130 131 132 133 134 135 136 137 |
# File 'lib/timet/database_syncer.rb', line 130 def insert_item_from_hash(db, item) fields = ['id', *ITEM_FIELDS].join(', ') placeholders = Array.new(ITEM_FIELDS.length + 1, '?').join(', ') db.execute_sql( "INSERT INTO items (#{fields}) VALUES (#{placeholders})", get_item_values(item, include_id_at_start: true) ) end |
#items_to_hash(items) ⇒ Hash
Converts database items to a hash indexed by ID
165 166 167 |
# File 'lib/timet/database_syncer.rb', line 165 def items_to_hash(items) items.to_h { |item| [item['id'], item] } end |
#open_remote_database(remote_path) ⇒ SQLite3::Database
Validates that the database connection is properly initialized
Opens and validates a connection to the remote database
65 66 67 68 69 70 |
# File 'lib/timet/database_syncer.rb', line 65 def open_remote_database(remote_path) db_remote = SQLite3::Database.new(remote_path) raise 'Failed to initialize remote database' unless db_remote db_remote end |
#process_database_items(local_db, remote_db) ⇒ void
This method returns an undefined value.
Processes items from both databases and syncs them
93 94 95 96 97 98 99 100 101 102 |
# File 'lib/timet/database_syncer.rb', line 93 def process_database_items(local_db, remote_db) remote_items = remote_db.execute('SELECT * FROM items ORDER BY updated_at DESC') local_items = local_db.execute_sql('SELECT * FROM items ORDER BY updated_at DESC') sync_items_by_id( local_db, items_to_hash(local_items), items_to_hash(remote_items) ) end |
#process_existing_item(*args) ⇒ Symbol
Processes an item that exists in both databases
146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/timet/database_syncer.rb', line 146 def process_existing_item(*args) id, local_item, remote_item, local_db = args local_time = local_item['updated_at'].to_i remote_time = remote_item['updated_at'].to_i if remote_wins?(remote_item, remote_time, local_time) puts (id, remote_item, 'Remote') update_item_from_hash(local_db, remote_item) :local_update elsif local_time > remote_time puts (id, local_item, 'Local') :remote_update end end |
#remote_wins?(remote_item, remote_time, local_time) ⇒ Boolean
Determines if remote item should take precedence
175 176 177 |
# File 'lib/timet/database_syncer.rb', line 175 def remote_wins?(remote_item, remote_time, local_time) remote_time > local_time && (remote_item['deleted'].to_i == 1 || remote_time > local_time) end |
#sync_databases(*args) ⇒ void
This method orchestrates the entire database synchronization process
This method returns an undefined value.
Synchronizes the local and remote databases by comparing and merging their items
81 82 83 84 85 86 |
# File 'lib/timet/database_syncer.rb', line 81 def sync_databases(*args) local_db, remote_db, remote_storage, bucket, local_db_path = args process_database_items(local_db, remote_db) remote_storage.upload_file(bucket, local_db_path, 'timet.db') puts 'Database sync completed' end |
#sync_items_by_id(local_db, local_items_by_id, remote_items_by_id) ⇒ void
This method returns an undefined value.
Syncs items between local and remote databases based on their IDs
110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/timet/database_syncer.rb', line 110 def sync_items_by_id(local_db, local_items_by_id, remote_items_by_id) all_item_ids = (remote_items_by_id.keys + local_items_by_id.keys).uniq all_item_ids.each do |id| if !remote_items_by_id[id] puts "Local item #{id} will be uploaded" elsif !local_items_by_id[id] puts "Adding remote item #{id} to local" insert_item_from_hash(local_db, remote_items_by_id[id]) else process_existing_item(id, local_items_by_id[id], remote_items_by_id[id], local_db) end end end |
#sync_with_remote_database(*args) ⇒ void
Configures both databases to return results as hashes for consistent data handling
This method returns an undefined value.
Performs the actual database synchronization by setting up connections and syncing data
51 52 53 54 55 56 57 |
# File 'lib/timet/database_syncer.rb', line 51 def sync_with_remote_database(*args) local_db, remote_path, remote_storage, bucket, local_db_path = args db_remote = open_remote_database(remote_path) db_remote.results_as_hash = true local_db.instance_variable_get(:@db).results_as_hash = true sync_databases(local_db, db_remote, remote_storage, bucket, local_db_path) end |
#update_item_from_hash(db, item) ⇒ void
This method returns an undefined value.
Updates an existing item in the database with values from a hash
195 196 197 198 199 200 201 |
# File 'lib/timet/database_syncer.rb', line 195 def update_item_from_hash(db, item) fields = "#{ITEM_FIELDS.join(' = ?, ')} = ?" db.execute_sql( "UPDATE items SET #{fields} WHERE id = ?", get_item_values(item) ) end |